I decided to write a review of libraries with the help of which it is easy and convenient to write applications for Android.
The list appears like this:
If interested, I ask for cat.
It is necessary to begin with the fact
that languages ​​are not my strong point; I will in advance forgive forgiveness for why there are so many libraries, why this is due and why it is necessary.
Naturally, everything is dictated by the application architecture. Based on my experience, it is almost always necessary to have the following structure of the application:

As you can see, the application is divided into 3 layers - “face”, data storage and service for asynchronous commands, where logic is almost always hidden.
I do not want to breed holivar and argue about architecture, I just describe how I do it and how my colleagues do.
A few words why so
Content provider is a very powerful thing with data change notifications and it's all out of the box. Yuzay mostly as a wrapper over the base. I did not find a way to get the data loading from the Internet there.
')
Service of asynchronous commands - everything is clear from the name, performs actions asynchronously (in another thread). Almost all actions should be asynchronous - writing to the base, going to the Internet, and even counting.
Why "asynchronous commands"? Here, too, everything is simple - every action is a complete command. Which knows with what parameters to start, what to do with them and notification of its completion.
Here
evilduck has already described everything in detail.
"Muzzle" - a set of activit / fragments to display data. I want to note that all data loading from the storage should be asynchronous (no trips to the database from the UI, even for one number). And here the loader manager comes to the rescue - also a feature out of the box. It is worth looking in the direction of the CursorLoader
Bicycle
Probably every programmer made his own bike. There is a benefit from them too - you begin to understand all the pitfalls, what and why is needed. But writing a bike every time is not good. And roll it from another project can not be because The code is sold and is the property of the customer.
Of course, your code can be arranged in lib, publish it, in the contract with the customer write that we use lib. But writing a lib for all occasions is not so easy, especially since doing another bike if you already have one, and bugs have already been found and fixed. So in the end happened to me.
I am not that the opponent is reflexed, but I prefer the ones that generate the code. It is convenient to debug, and you can always see what's going on there.
Everything else I like annotations. My whole library selection practically corresponds to this principle. Let's start ...
Groundy
This library implements command service.
- Teams can be kenselit
- AsyncTask lovers will not notice the transition
- There is support for Kalbek and they are very easy to use.
I prefer to write a static method for running a command and typing a kalbek.
Although a kalbek can be any object I prefer to type it. This will help the compiler to help us.
And it will protect you from the temptation to hang Kalbeki on public activation methods, thereby breaking one of the pillars of the PLO - encapsulation :)
For the same reasons, a static launch method is needed.
public class LoginCommand extends GroundyTask{ private static final String ARG_PASSWORD = "arg_password"; private static final String ARG_USER = "arg_username"; @Override protected TaskResult doInBackground() { String userName = getStringArg(ARG_USER); String password = getStringArg(ARG_PASSWORD);
Retrofit
Very simple tool for calling REST services, both well written and not so well. The code really does not generate, but is very simple.
I looked in the direction of Spring Android, but somehow it is too heavy.
public interface ServicesFootballua { String API_URL = "http://services.football.ua/api"; @GET("/News/GetArchive") NewsArchive getNewsArchive(@Query("pageId") long pageId, @Query("count") long count, @Query("datePublish") String date); }
Well, like this
private static ServicesFootballua API = new RestAdapter.Builder() .setServer(ServicesFootballua.API_URL) .build() .create(ServicesFootballua.class); ................................... archive = API.getNewsArchive(PAGE_ID, COUNT, dateFormat.format(getTodayTime()));
You can substitute your converter, http client and a lot of other things.
AnnotatedSQL
Generate database and content provider by annotations.
My crafts, I am completely satisfied. A couple of articles are on Habré -
here and
here .
Recently, with a kick of
evilduck published in maven central
I looked at ORMLite, but it seems to me that it is not suitable for android. Usually we don’t need to pull anything and everything straight. Normal sql and vyshki solve almost everything.
Android Annotations
I watched this lib very long and recently decided to start using it in production - I liked it, despite the fact that you need to use the learned classes.
The most powerful tool, the main thing is not to use
Background well or turn on the head.
A good plus is that you can cut it out almost painlessly.
I looked at AQuery and Dagger, but IMHO Android Annotations - already has it all.
The only negative is that sometimes it’s hard to look for the error “why not compile?”.
About all the features you can read on the off site. The only thing I want to add is that I always write a static method to launch activation, create a fragment. This isolates all the code in one place and no one in the code knows whether we are using the original class or the original.
For example, the
AlertDialogFragment fragment will have a method
public static void show(FragmentActivity activity, DialogType type, int titleId, String msg, int positiveTitleId, OnDialogClickListener positiveListener) { DialogUtil.show(activity, DIALOG_NAME, AlertDialogFragment_.builder() .titleId(titleId) .errorMsg(msg) .positiveButtonTitleId(positiveTitleId) .dialogType(type).build() ).setOnClickListener(positiveListener); }
and everywhere in the code the call will be
AlertDialogFragment.show(BaseActivity.this, DialogType.CONFIRM, R.string.some_title, getString(R.string.some_message), R.string.btn_edit, new OnDialogClickListener() {...............}
and no one knows about the existence of
AlertDialogFragment_Android db-commons
Recently found this wonderful libu. Since we use loaders everywhere, usually the result is Cursor. You can always use a CursorAdapter and display what you need.
But this one offers us a list (List), but above the cursor, and with the list everyone's favorite ArrayAdapter.
This is a symbiosis - you can see the List and use the ArrayAdapter, but in fact it’s a cursor and an adapter cursor. Real "street magic" :)
The guys were not lazy and wrote such a LazyList with a small cache inside, everything is as it should be - inside LruCache.
In order to get the List instead of the Cursor, you need to write a function (
transform ) to convert the cursor string to an object and you will get a loader that returns not the Cursor, but the List
return CursorLoaderBuilder.forUri(URI_ITEMS) .projection(ItemConverter.PROJECTION) .where(ItemTable.ACTIVE_STATUS + " = ?", 1) .where(ItemTable.DESCRIPTION + " like ?", "%" + searchText + "%") .transform(new ItemConverter()).build(getActivity());
But as we know, sometimes you have to read the cursor into some object, for example, you need to count something, for that the guys have a
wrap method
public Loader<Integer> onCreateLoader(int i, Bundle bundle) { return CursorLoaderBuilder .forUri(ITEMS_URI) .projection("count(" + ItemTable.GUID + ")") .where(ItemTable.ACTIVE_STATUS + " = ?", 1) .where(ItemTable.STOCK_TRACKING + " = ?", 1) .where(ItemTable.TMP_AVAILABLE_QTY + " <= " + ItemTable.RECOMMENDED_QTY) .wrap(new Function<Cursor, Integer>() { @Override public Integer apply(Cursor c) { if (c.moveToFirst()) { return c.getInt(0); } return 0; } }).build(DashboardActivity.this); }
Here is such a simple way.
This is a very trivial example. The possibilities are much cooler.
In this case, the wrap method is still executed in another thread. so you can still go to the database for more data.
As I said it sometimes is necessary.
Ending
It is clear that for the UI itself a handful of different libs are used (mainly components), but this already depends on the designer’s imagination :)
Well, here is a piece of build script for graidl that apt wound up (
yes, there is already a special plugin, but have not tried it yet ).
Oh yes - download
android-db-commons-0.1.6.jar to the libs folder
ext.androidAnnotationsVersion = '2.7.1'; configurations { apt } dependencies { compile fileTree(dir: 'libs', include: '*.jar') compile 'com.google.guava:guava:13.0.1' compile 'com.telly:groundy:1.3' apt 'com.telly:groundy-compiler:1.3' apt "com.googlecode.androidannotations:androidannotations:${androidAnnotationsVersion}" compile "com.googlecode.androidannotations:androidannotations-api:${androidAnnotationsVersion}" compile 'com.github.hamsterksu:android-annotatedsql-api:1.7.8' apt 'com.github.hamsterksu:android-annotatedsql-processor:1.7.8' } android.applicationVariants.all { variant -> aptOutput = file("${project.buildDir}/source/apt_generated/${variant.dirName}") variant.javaCompile.doFirst { aptOutput.mkdirs() variant.javaCompile.options.compilerArgs += [ '-processorpath', configurations.apt.getAsPath(), '-processor', 'com.annotatedsql.processor.provider.ProviderProcessor,com.annotatedsql.processor.sql.SQLProcessor,com.googlecode.androidannotations.AndroidAnnotationProcessor,com.telly.groundy.GroundyCodeGen', '-AandroidManifestFile=' + variant.processResources.manifestFile, '-s', aptOutput ] } }
Thank you all for your attention