Recently, I learned MVP, Retrofit2, Rx Java2 framework. I feel I have gained a lot, so I decided to make use of my knowledge to do a great job.
ps: You can see my previous blog about children's shoes that are not clear about these three frameworks
Portal:
MVP
Retrofit2
RxJava2
Design sketch
Let's not say much. Let's start with the picture.
Barely able to see the past.
So the most important thing is coming.
That is
Realization
First of all, the background api interface I use here is the interface of gentle weather. It's completely free and practical. You can register one.
Wind weather
This interface will provide a lot of weather information. We just need to get what we want.
1. Modify the build.gradle file to introduce dependencies
//recyclerview
implementation 'com.android.support:recyclerview-v7:28.+'
//retrofit2
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
//Rxjava and Retrofit (Retrofit+Rx dependencies to be added)
implementation 'com.squareup.retrofit2:adapter-rxjava:2.4.0'
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'io.reactivex:rxjava:1.2.1'
//TextInputLayout
implementation 'com.android.support:design:28.+'
2. Look at the data style behind the scenes.
Build our bean s in json format for receiving data
Because the bean class is too long, I will not show it here. Interested friends can see my source code.
3. Create Retrofit's api interface for writing request data
public interface DataRequest {
//Get weather data, base URL declares in the model class
@GET("now")
Observable<Weather> getNowWeather(@Query("location")String location,@Query("key")String key);
}
4. Build your own MVP architecture
Let's first think about what needs to be done at each level.
view: Data is retrieved from the model layer and displayed on the interface through presenter, so we build a setWeather method and pass a location to tell the model layer where we want to retrieve the data.
presenter: Connect model and view, so the method is a collection of model and view methods
model: Get data from the view layer through presenter, and use Retrofit to send data requests to the background.
With the blueprints for the project, it's time for us to build the building.
MainContract
public class MainContract {
public interface Presenter{
//Obtaining weather data
void getWeather(String location);
//Set the weather to view
void setWeather(List<Weather> weathers);
}
public interface View{
//Successful data acquisition
void getSuccess();
//Acquisition failure
void getFailed();
//Display data on view
void setWeather(List<Weather> weathers);
}
}
MainPresenter (concrete implementation of Presenter)
public class MainPresenter implements MainContract.Presenter{
private MainRepository mainRepository;
private MainContract.View mainView;
public MainPresenter(MainContract.View mainView) {
mainRepository = new MainRepository(this);
this.mainView = mainView;
}
@Override
public void getWeather(String location) {
mainRepository.getWeather(location);
}
@Override
public void setWeather(List<Weather> weathers) {
mainView.setWeather(weathers);
}
}
MainRepository (Specific implementation of request data method, which uses Retrofit+RxJava)
public class MainRepository {
private final static String KEY = "Your own key";
private final static String TAG = "MainRepository";
private final static String BASE_URL = "https://free-api.heweather.com/s6/weather/";
private List<Weather> weathers = new ArrayList<>();
private MainContract.Presenter presenter;
public MainRepository(MainContract.Presenter presenter) {
this.presenter = presenter;
}
/**
* Obtaining weather data
* @param location City
* @return Weather Class data
*/
public void getWeather(String location){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
DataRequest dataRequest = retrofit.create(DataRequest.class);
dataRequest.getNowWeather(location,KEY)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Weather>() {
@Override
public void onCompleted() {
presenter.setWeather(weathers);
Log.d(TAG, "onCompleted: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLocation());
}
@Override
public void onError(Throwable e) {
Log.d(TAG, "onError: " + e.getMessage());
}
@Override
public void onNext(Weather weather) {
weathers.add(weather);
Log.d(TAG, "onNext: " + weather.getHeWeather6().get(0).getBasic().getLocation());
}
});
weathers.clear();
}
}
MainActivity (Implementation of View Layer, ps: Part of Code)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
onClick();
}
public void init(){
presenter = new MainPresenter(this);
editText = findViewById(R.id.et_city);
tAdminArea = findViewById(R.id.t_admin_area);
tCnty = findViewById(R.id.t_cnty);
tCondTxt = findViewById(R.id.t_cond_txt);
tFl = findViewById(R.id.t_fl);
tHum = findViewById(R.id.t_hum);
tLat = findViewById(R.id.t_lat);
tLoc = findViewById(R.id.t_loc);
tLocation = findViewById(R.id.t_location);
tLon = findViewById(R.id.t_lon);
tParentCity = findViewById(R.id.t_parent_city);
tTmp = findViewById(R.id.t_tmp);
tWindDir = findViewById(R.id.t_wind_dir);
tWindSc = findViewById(R.id.t_wind_sc);
tWindSpd = findViewById(R.id.t_wind_spd);
bSearch = findViewById(R.id.b_search);
background = findViewById(R.id.background);
//Hide the title bar
ActionBar actionBar = getSupportActionBar();
if(actionBar != null){
actionBar.hide();
}
}
public void onClick(){
bSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sCity = editText.getText().toString();
presenter.getWeather(sCity);
Log.d(TAG, "onClick: " + sCity);
//Hide Soft Keyboard
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
}
});
//Enter key monitoring
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
if (i == EditorInfo.IME_ACTION_UNSPECIFIED) {
sCity = editText.getText().toString();
presenter.getWeather(sCity);
Log.d(TAG, "onClick: " + sCity);
//Hide Soft Keyboard
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
}
return false;
}
});
}
@Override
public void getSuccess() {
Toast.makeText(getApplicationContext(),"Successful data acquisition",Toast.LENGTH_SHORT).show();
}
@Override
public void getFailed() {
Toast.makeText(getApplicationContext(),"Failure to obtain data",Toast.LENGTH_SHORT).show();
}
@Override
public void setWeather(List<Weather> weathers) {
tWindSpd.setText("wind speed: " + weathers.get(0).getHeWeather6().get(0).getNow().getWindSpd() + "kilometre/hour");
tWindSc.setText("wind power: " + weathers.get(0).getHeWeather6().get(0).getNow().getWindSc() + "level");
tWindDir.setText("wind direction: " + weathers.get(0).getHeWeather6().get(0).getNow().getWindDir());
tTmp.setText("temperature: " + weathers.get(0).getHeWeather6().get(0).getNow().getTmp() + "℃");
tParentCity.setText("city: " + weathers.get(0).getHeWeather6().get(0).getBasic().getParentCity());
tLon.setText("longitude: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLon());
tLocation.setText("region: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLocation());
tLat.setText("latitude: " + weathers.get(0).getHeWeather6().get(0).getBasic().getLat());
tHum.setText("relative humidity: " + weathers.get(0).getHeWeather6().get(0).getNow().getHum());
tFl.setText("Somatosensory temperature: " + weathers.get(0).getHeWeather6().get(0).getNow().getFl() + "℃");
tCondTxt.setText("Weather condition: " + weathers.get(0).getHeWeather6().get(0).getNow().getCondTxt());
tCnty.setText("Country: " + weathers.get(0).getHeWeather6().get(0).getBasic().getCnty());
tAdminArea.setText("province: " + weathers.get(0).getHeWeather6().get(0).getBasic().getAdminArea());
addWeatherPhoto();
}
In this way, is it easy to complete the project? MVP architecture makes our whole project very clear. Retrofit enables us to easily implement network requests. Rxjava cooperates with Retrofit. The whole code is a chain and can switch threads freely. It's simply too convenient!
I'm really grateful to see my friends who talk nonsense here. As a new white man, there are still more ways to go in the future. I hope to make progress with you. Thank you for watching, God of God!
Finally, I attach the project address on my github:
github portal