android Weather app Based on MVP,Retrofit2,RxJava2

Keywords: Retrofit github Android Gradle

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

Posted by tanvirtonu on Sat, 29 Dec 2018 09:42:07 -0800