📜 ⬆️ ⬇️

Cheat Sheet or Must have for Android Developer

The article was created for developers who wish to find new tools and libraries to further simplify the routine of life.

So, let's begin.

Butterknife


The library was developed by Square and immediately caught on with the developers. ButterKnife was created to replace findViewById in order to reduce an already bloated activity :
')
 View someView = (View) findViewById(R.id.someView) 

Just see how long the line is! And if this is a class field, then there are two whole lines:

 View someView; //  ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); someView = (View) findViewById(R.id.someView); //  } 

Now for ButterKnife. Here is a simple code example from ButterKnife:

  @BindView(R.id.someView1) View view1; @BindView(R.id.someView2) View view2; @BindView(R.id.someView3) View view3; ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); //  } 

It's very simple: using the @BindView annotation @BindView we tell which view we need, and then the main thing is not to forget about ButterKnife.bind(this); (You need to do this in activation, for other places like holder or fragment, they do it a little differently. See here .

How to add to the project?

Gradle (app module):

  compile 'com.jakewharton:butterknife:8.5.1' apt 'com.jakewharton:butterknife-compiler:8.5.1'  annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'  jack 

Retrofit 2


The Square company has created not only ButterKnife, but also many other excellent libraries without which many developers cannot imagine their life. One of these libraries is Retrofit 2.

It was created in order to simplify work with the REST API. Previously, to make a request, you had to turn up the mountains of code, but now everything is different. So how do you make a request?

Add to gradle (app module):

  compile 'com.google.code.gson:gson:2.7' compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' //  rxJava    compile 'io.reactivex.rxjava2:rxjava:2.0.1' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' 

First, take the site to convert from json to pojo like this and copy all the classes that were generated in AndroidStudio:

image

Then they create an interface (I use retrofit with RxJava):

 public interface IWeatherProvider{ @GET("/premium/v1/weather.ashx") Observable<Model> getWeather(@QueryMap Map<String, String> map); } 

In QueryMap throw query parameters (for example api key). Although instead of @QueryMap, you can use just Query, but then for each parameter you need to register your query.

Thereafter:

 Retrofit retrofit = Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .baseUrl(Constants.WEATHER_BASE_URL) .build(); ... retrofit.create(IWeatherProvider); 

Then you need to fill the parameters with the data:

 HashMap<String, String> mapJson = new HashMap<>(); mapJson.put("key", Constants.WEATHER_API_KEY); mapJson.put("q", latitude + "," + longitude); mapJson.put("num_of_days", "14"); mapJson.put("date", "today"); mapJson.put("format", "json"); 

And call iweatherProvider.getWeather(mapJson);

And finally:

 new CompositeDisposable().add(weatherProvider .observeOn(Schedulers.newThread()) .subscribeOn(Schedulers.io()) .subscribe(onNext, onError)); 

In case you are not using RxJava, replace Observable with Call in the interface and make

 iweatherProvider.getWeather(mapJson).enqueue(callback); 

Dagger 2


Created by Google. Helps to implement the Dependency Injection pattern. With the help of Dagger, you can coolly structure the project, which is very good for the readability of the code and helps in testing (by the way, using retrofit along with dagger is the pleasure itself). The point is that all classes want to work with ready-made data, they just need to get them, and do something with them. But someone must provide data. The dagger takes on this role. The basis of the Dagger is the components, here is one of them:

 @Component(modules = {WeatherInfoTaskModule.class}) public interface RetrofitComponent { void inject(MainActivity activity); } 

All components consist of modules, in one component there can be several modules, here is an example of a module:

 @Module public class WeatherInfoTaskModule { @Provides Gson provideGson() { Log.d(TAG, "gson"); return new GsonBuilder().create(); } @Provides IWeatherProvider provideWeather(Retrofit retrofit) { Log.d(TAG, "weather"); return retrofit.create(IWeatherProvider.class); } @Provides Retrofit provideRetrofit(Gson gson) { Log.d(TAG, "retrofit"); return new Retrofit.Builder() .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .baseUrl(Constants.WEATHER_BASE_URL) .build(); } } 

Inside the modules, there are functions with Provides annotation, as it follows from the annotation they supply data. Basically, these functions are divided into modules by meaning (for example, geolocation). And here a logical question arises, how to use it?

Very simple. In your activation, mark the fields that should receive data with the Inject annotation ( @Inject IWeatherProvider mWeatherProvider; ). Then create your Application class:

 public class App extends Application { private static RetrofitComponent component; @Override public void onCreate() { super.onCreate(); component = DaggerRetrofitComponent.create(); } public RetrofitComponent getComponent() { return component; } } 

In the MainActivity in OnCreate, do the following:

 @Inject IWeatherProvider mWeatherProvider; ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((App) getApplicationContext()).getComponent().inject(this); } 

PS Don't forget to add the App class to the manifest.

In gradle (app):

 buildscript { repositories { mavenCentral() } dependencies { classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' } } apply plugin: 'com.neenbedankt.android-apt' apply plugin: 'android-apt' dependencies{ compile 'com.google.dagger:dagger:2.7' apt 'com.google.dagger:dagger-compiler:2.7' } 

in gradle (project module):

  classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 

But what if one of the functions at the input also need data? In this case, the dagger runs over the component in search of a function that returns the required class or data type, and when it finds it, it calls.

What happens if I change the name of the function? Dagger doesn’t care about the name, he is interested only in signatures, so it doesn’t affect his work.

Studio highlights class DaggerRetrofitComponent are red. What to do? Dagger works on code generation, so in such a case it’s just worth rebuild.

Multidex


Sooner or later, the developer is faced with the problem of 65 thousand methods. But let's start over. When you want to install the application on your phone you need an apk file. The basis of any apk file is dex file. Dex file - these are your java classes collected in one file. But the dex file has a limit of 65 thousand methods. And most applications exceed this limit and get exception when building. For such cases, created multidex. In gradle (app module) add:

 ... defaultConfig { ... multiDexEnabled true ... } ... compile 'com.android.support:multidex:1.0.1' 


Thanks to int00h , I will correct previously erroneous information.
There are 3 ways to connect MultiDex:



The post came out long, but I hope that the hot has somehow explained. What libraries do you use?

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


All Articles