📜 ⬆️ ⬇️

Aibolit for android

How tedious is the UI initialization process when developing android applications. Time after time you have to write the mountains of the template code: findViewbyId, setOnClickListener, getResources (). GetDrawable, ... There is a natural desire to shift this work to AOP shoulders. A quick search for ready-made solutions adapted for android, brought only RoboGuice , which was already mentioned on Habré. However, the library has a significant size (~ 0.5 mb), which is unacceptable for many applications, and also requires the inheritance of your application and activity classes from RoboApplication and RoboActivity, which you don’t always want to do. That's why Aibolit appeared, lightweight (~ 40kb), an easy-to-use and functional library that uses dependency injection to initialize the UI on android.


Opportunities




Usage example


We connect dependence:
repositories { maven { url 'https://dl.bintray.com/alexeydanilov/maven' } } dependencies { compile 'com.danikula:aibolit:1.0' } 

and inject
 public class AibolitChatActivity extends Activity { // annotate fields to be injected... @InjectView(R.id.messageEditText) private EditText messageEditText; @InjectView(R.id.historyListView) private ListView historyListView; @InjectResource(R.string.symbols_count) private String symbolsCountPattern; @InjectSystemService(Context.NOTIFICATION_SERVICE) private NotificationManager notificationManager; @InjectService private HttpManager httpManager; @InjectResource(R.layout.content) private View content; ... @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.chat_activity); // initialize annotated fields and methods Aibolit.doInjections(this); // or just Aibolit.setInjectedContentView(this); ... } // annotate event handlers... @InjectOnClickListener(R.id.sendButton) private void onSendButtonClick(View v) { // handle onClick event } @InjectOnClickListener(R.id.clearHistoryButton) private void onClearHistoryButtonClick(View v) { // handle onClick event } @InjectOnTextChangedListener(R.id.messageEditText) public void onMessageTextChanged(CharSequence s, int start, int before, int count) { // handle text changed event } ... } 

The code is very simple; it is completely free from calls to the findViewById, setOnClickListener, and the like. Instead of this:
  1. mark the view, which should be initialized using the InjectView annotation;
  2. we define event handlers and mark them with appropriate annotations InjectOn *. In this example, event handlers for clicking on a button and changing text were defined. Aibolit allows you to add handlers for all major events:
    OnClick, OnLongClick, OnTouch, OnKey, OnTextChanged, OnCheckedChange, OnFocusChange, OnItemClick, OnItemSelected, OnEditorAction, OnCreateContextMenu;
  3. call the Aibolit.doInjections(this); method Aibolit.doInjections(this); after you set the content to activate.

Call two methods
 setContentView(layoutId); Aibolit.doInjections(this); 

can be replaced by one:
 Aibolit.setInjectedContentView(this); 

Aibolit also allows you to inject application services to an application, as is done in the example above:
 @InjectService private HttpManager httpManager; 

More details on this can be found in the Aibolit class documentation.

How it works


The source code is open and documented. What happens behind the scenes? Aibolit analyzes the class for the presence of fields and methods marked with Inject * annotations. For each annotation, its own class-injector is defined, which is responsible for initializing the field by one or another resource. Below is an example of such an injector responsible for initializing the view:
 class ViewInjector extends AbstractFieldInjector<InjectView> { @Override public void doInjection(Object fieldOwner, InjectionContext injectionContext, Field field, InjectView annotation) { int viewId = annotation.value(); View view = injectionContext.getRootView().findViewById(viewId); if (view == null) { // throw exception... } if (!field.getType().isAssignableFrom(view.getClass())) { // throw exception... } try { field.setAccessible(true); field.set(fieldOwner, view); } catch (IllegalArgumentException e) { // throw exception... } catch (IllegalAccessException e) { // throw exception... } } } 

Performance


In order not to give reasons for holivars, I will give just dry numbers. Measurements were made on the emulator. It was necessary to initialize 35 elements (view, licensed, application resources). When using the classical approach to the transition from one activation to another, it took 40-50 ms, while using aibolit - 90-100 ms. As expected, the reflection-based approach is more time-consuming, but the difference obtained, IMHO, is not significant.
')
Aibolit can be used as a finished product or as a basis for writing your own solution. The library code is open and distributed under the Apache License, Version 2.0.
I will be glad to comments and suggestions.

UPD 0:
Similar libraries
roboguice
androidannotations

Source: https://habr.com/ru/post/132126/


All Articles