Day35 MVP architecture, dagger 2, butterknife usage

Brief introduction to butterKnife framework

ButterKnife is a View injection framework focusing on Android systems. It used to write a lot of findViewById to find View objects. With ButterKnife, these steps can be easily eliminated.

ButterKnife - > For UI Annotation Class Framework
-> Setting up listener lookup controls
-> Eliminate findviewbyid, setOnclicklistener
1. Import dependency
2. Declaring control variables - > access modifiers cannot inject control objects for private - > effects
3. Bind controls with @BindView
4. Use @Onclik to add click events

Dependence:

implementation 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'

activity

public class MainActivity extends AppCompatActivity {

    @BindView(R.id.my_RecyclerView)
    public RecyclerView recyclerView;
    ArrayList<String> arrayList = new ArrayList<>();
    MyRecycleView_Adapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        arrayList.add("Ha-ha");
        arrayList.add("Ha-ha");
        arrayList.add("Hey");
        adapter = new MyRecycleView_Adapter(arrayList,this);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);
    }
}
public class MyRecycleView_Adapter extends RecyclerView.Adapter<MyRecycleView_Adapter.MyViewHolder> {

    ArrayList<String> arrayList;
    Context context;

    public MyRecycleView_Adapter(ArrayList<String> arrayList, Context context) {
        this.arrayList = arrayList;
        this.context = context;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(context).inflate(R.layout.my_recycleview_item,viewGroup,false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder myViewHolder, int i) {
        myViewHolder.textView.setText(arrayList.get(i));
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder{

        @BindView(R.id.item_text)
        TextView textView;
        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            ButterKnife.bind(this,itemView);
        }
    }
}

Dagger2

Framework description
Reduce boilerplate code; Improve reusability, testability and maintainability.

Write @Inject on the constructor of the object class, inject the object directly when needed, avoid new objects and cause strong coupling. And you can add a comment @Singleton to form a singleton.

Based on @module and @provides, objects can be injected arbitrarily and can be operated with parameters. If there are other modules in Module, write them in includes, @Module in addition to include, there are injects parameters to specify the injection location, library to specify whether external libraries are needed, and completion is a complete module (including external module dependencies is incomplete). Finally, at the injection destination, the dependency relationship is formed by ObjectGraph (Object Graph), the specific operation mode, ObjectGraph object, and the method create (Module). inject (Injection Object); then @inject can be injected directly into the target object class.

Difference between Dagger 2 and butterknife

Buffer knife is designed to inject into view, so it can be injected into non-active or inflate views.

Dagger can be injected into any object you want, as long as it is in the module class. Or it's a constructor. However, there is no support for method and field injection.

Buffer knife just avoids boilerplate code, findViewById, and that's all, so it's not really an injection. It's just the voice of a view.

For Dagger, we can think of it as a module in the application.
Responsible for providing instances for other modules and injecting dependencies. That is its basic duty. Module creation is at one point in our application, so that we can have complete control. Dagger
Leiva says it's particularly suited for low-end devices because it uses precompiled technology instead of reflection, because reflection-based DI is very resource-intensive and time-consuming. Dagger may not be the ideal framework for dependency injection, but Leiva believes it is the most efficient.

Dagger2 relies on imports:

implementation 'com.google.dagger:dagger:2.19'
annotationProcessor 'com.google.dagger:dagger-compiler:2.19'

Dagger 2 Note Notes:

@Inject
Inject has two main functions: one is to use it on the constructor and let Dagger 2 use it through the tag constructor (Dagger 2 can find the constructor when it needs the class instance and new out the relevant instance by the injection tag) to provide dependency; the other is to tag the dependency when it needs the class instance. Variables let Dagger2 provide dependencies for them.

@Provide
Provide is used to annotate a method that can be invoked when dependencies need to be provided, thus assigning pre-provided objects as dependencies to variables annotated with @Injection. Provide is mainly used to annotate methods in Module

@Module
Classes annotated with Module are specifically designed to provide dependencies. Some people may have some doubts. Looking at the @Inject above, we need to tag the constructor to provide dependencies. What if the class constructor we need to provide can not be modified, such as some classes in the jar package, we can not modify the source code. At this point, you need to use Module. Module can provide dependencies for classes that cannot modify source code, and of course, dependencies can also be provided through Module, which can be annotated with Inject.

@ Component is commonly used to annotate interfaces. Component-annotated interfaces generate instances of corresponding classes when compiled to serve as bridges between providers and needy dependents and inject relevant dependencies into them.

@ Scope: Scope, Dagger2 defines scope by customizing annotations, with a default scope annotation @Singleton, commonly used in Android to mark instances that live throughout the life cycle of App. You can also customize a @PerActivity,@PerFragment annotation to indicate that the instance lifecycle is consistent with Activity and Fragment. We can customize the granularity of scopes (such as @PerUser, etc.).

@ Qualifier: Qualifier. We can use this annotation when the type of a class is insufficient to indicate a dependency. For example, if we have two @Provide annotations that require a String parameter, we can distinguish between Dagger2 with a qualifier @Named annotation and Dagger2 with a custom identifier @ForData or @ForImage, which can be identified by @Named ("xxxxx x"). .

@ SubComponent: If we need all the provided objects of the parent component, then we can use the inclusion method instead of the dependency method. Compared with the dependency method, the inclusion method does not need the explicit exposed objects of the parent component (the dependency method can only get the exposed instances), so we can get all the objects of the parent component. And SubComponent only needs to be declared in the parent Component interface.

@ Named(@) Since Dagger2 has been injected using type inference, objects of the same type can not be distinguished. The @Named annotation can be used to distinguish objects of the same type, which can be understood as an alias for objects.

Dagger2 basically uses:

Create Inject2 class and use the @Inject tag construction method to provide dependencies to other classes;
Create Inject1 class to declare Inject2 variable and use Inject annotation;
Create show method under Inject1, call show method under inject2 to create InjectComponent interface using Component annotation;
Create inject methods to provide inject1 with dependencies on inject2
Use DaggerInjectComponent.builder().build().inject(this) in the show method of Inject1; get dependencies

Dagger2 complex use:

Creating ShowUtils class is responsible for concrete display logic.
Create ShowInject class and use Inject tag to mark ShowUtils variable to introduce dependencies;
Create ShowModules class, use the Provides tag tagging method of Modules tagging management method, and use new keywords to create objects of dependent classes;
Create the ModulesComponent interface using @Component (modules = ShowModules. class})
Declare the management class ShowModules and create dependent methods

Summary

Dagger 2 - > Dependency Injection Framework - > Injecting Class Objects into Projects
-> Why use dagger2? Decoupling - > Objects are not created directly in Activity
Basic Use: 1. Create Show InjectUtils
2. Create a show method - > Use the method under the current class
3. Rewrite the constructor - > add the @Inject tag to the constructor - > the current class object is injected into other classes through dagger2
4. Write variables under MainActivity to receive injected objects using @Inject
5. ShowCompont (Dagger 2 Injection Object Bridge)
6. Write the abstract method inject - > to declare where the object is injected
7. Construction Project - > Hammer
8. Call Dagger2
Advanced Use: 1. Create ShowModules InjectUtils
2. Create a show method - > Use the method under the current class
3. Rewrite the constructor - > add the @Inject tag to the constructor
4. Create a warehouse class ShowModules - > to provide objects to bridges
5. Creating showProvider Method - > Providing Objects to Bridges
6. Building Bridges
7. Declaration under MainActivity
8. Construction
9. Use

public class ShowInjectUtils {

    @Inject
    public ShowInjectUtils() {
    }
    public void show(){
        Log.e("####","ShowInjectUtils    show");
    }
}
public class ShowModulesUtils {
    @Inject
    public ShowModulesUtils() {
    }

    public void show(){
        Log.e("####","ShowModulesUtils    show");
    }
}

New di package

@Component
public interface ShowComponent {
    void inject(MainActivity mainActivity);
}
@Component(modules = ShowModules.class)
public interface ShowModulesComponent {
    void inject(MainActivity mainActivity);
}
@Module
public class ShowModules {

    @Provides
    public ShowModulesUtils getInstance(){
        return new ShowModulesUtils();
    }

Hammer after creation
Automatically generate objects: build generate source apt debug com example dagger2_practice di DaggerShowComponent. Java

activity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    Button btn1,btn2;
    @Inject
    public ShowInjectUtils showInjectUtils;
    @Inject
    public ShowModulesUtils showModulesUtils;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn1 = findViewById(R.id.btn1);
        btn2 = findViewById(R.id.btn2);
        btn1.setOnClickListener(this);
        btn2.setOnClickListener(this);
        DaggerShowComponent.builder().build().inject(this);
        DaggerShowModulesComponent.builder().build().inject(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn1:
                showInjectUtils.show();
                break;
            case R.id.btn2:
                showModulesUtils.show();
                break;
        }
    }
}

MVP

Official website: https://github.com/JessYanCoding/MVPArms


mv c: There is no pure mvc in Android, only mv mode - > activity is equivalent to v and C - >.
Logic c C can't be reused - > Repeatedly write the same logic
mvp: model view presenter
mvp: google's official mvp architecture based on dagger 2 branch;
1. Create lib_core module-> framework building and secondary encapsulation of tripartite dependency framework;
2.lib_core:mvp Architecture Encapsulation
3. Write IModel - > Destruction Method - > Release Network Request
4. IPresenter - > Destruction Method - > Call model
5. IView - > show dialog (): Display request waiting dialog box;
hidedialog() closes the request dialog box; showtoast() error message;
6. BaseModel - > All model Base Classes
7. BasePresenter - > All Presenter base classes
8. BaseActivity - > All Activity Base Classes
mvp architecture uses:
1. Create mvp package - > concrete interface implementation
2. Create entity packages - > All entity classes
3. Creating base class of entity class under entity package - > BaseEntity - > entity class delivery can make use of java polymorphism to transition upward and downward.
4. Create Subscription Package under MVP - > Store Subscription Interface - > Specification View and Model in Subscription Interface
Request response method

step

1. Subcontracting
mvp ----> model view presenter contract
di ----> component modules
2. Entity classes corresponding to parsed data
entity
3.Api requests data
Api
4.contract Subscription
Implementation of Interface between IView and IModel
5.model specific request method inherits IXXXModel from BaseModel implementation subscription
6.XXXPresenter inherits from BasePresenter
7.di package modules
8.di package component
9.MainActivity inherits BaseActivity to implement IView interface

model -->entity

public class UploadEntity {
    public String statues;
    public String msg;
}
public class BrandGoodsEntity {

    public String msg;
    public List<Banner>banner;

    public class Banner{
        public String recommend_name;
        public String recommend_url;
    }

model–>api

public interface Api {
    String APP_DOMAIN = "http://169.254.163.202/yoho/";

    @Multipart
    @POST("upload_head.php")
    Observable<UploadEntity> uploadImg(@Part List<MultipartBody.Part> list);

    @FormUrlEncoded
    @POST("brand_goods.php")
    Observable<BrandGoodsEntity> brand_goodsPost(@Field("request")String request);

}

contract package

public interface UploadContract {

    interface IUploadView extends IView{
        //Upload Successful Callback Method
        void success(UploadEntity entity);
    }

    interface IUploadModel extends IModel{
        //Upload Picture Interface
        Observable<UploadEntity>uploadImg(List<MultipartBody.Part> list);
    }

}
public interface BrandGoodsContract {

    interface IBrandGoodsView extends IView {
        //Request Successful Callback Method
        void success(BrandGoodsEntity entity);
    }

    interface IBrandGoodsModel extends IModel {
        //Request Data Interface
        Observable<BrandGoodsEntity> getBrandGoods(String request);
    }

}

model package

@ActivityScope//Provide a unique object
public class UploadModel extends BaseModel implements UploadContract.IUploadModel {

    @Inject
    public UploadModel(IRepositoryManager repositoryManager) {
        super(repositoryManager);
    }

    @Override
    public Observable<UploadEntity> uploadImg(List<MultipartBody.Part> list) {
        return mRepositoryManager.obtainRetrofitService(Api.class).uploadImg(list);
    }
}
@ActivityScope
public class BrandGoodsModel extends BaseModel implements BrandGoodsContract.IBrandGoodsModel {

    @Inject
    public BrandGoodsModel(IRepositoryManager repositoryManager) {
        super(repositoryManager);
    }

    @Override
    public Observable<BrandGoodsEntity> getBrandGoods(String request) {
        return mRepositoryManager.obtainRetrofitService(Api.class).brand_goodsPost(request);
    }
}

presenter package

public class UploadPresenter extends BasePresenter<UploadContract.IUploadModel,UploadContract.IUploadView> {

    @Inject
    public UploadPresenter (UploadContract.IUploadModel model,UploadContract.IUploadView view){
        super(model,view);
    }

    //Specific request upload method
    public void upload(String path,String userID){
        File file = new File(path);
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);
        RequestBody body = RequestBody.create(MediaType.parse("multipart/form-data"),file);
        builder.addFormDataPart("uploadedfile",""+System.currentTimeMillis()+".png",body);
        builder.addFormDataPart("userid",userID);
        Observable<UploadEntity> observable = mModel.uploadImg(builder.build().parts());
        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<UploadEntity>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(UploadEntity entity) {
                        //Callback to activity
                        mRootView.success(entity);
                    }

                    @Override
                    public void onError(Throwable e) {

                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }

}
public class BrandGoodsPresenter extends BasePresenter<BrandGoodsContract.IBrandGoodsModel,BrandGoodsContract.IBrandGoodsView> {

    @Inject
    public BrandGoodsPresenter(BrandGoodsContract.IBrandGoodsModel mModel,BrandGoodsContract.IBrandGoodsView mRootView){
        super(mModel,mRootView);
    }

    public void getBrandGoods(){
        JSONObject jo = new JSONObject();
        try {
            jo.put("brand","1");
            jo.put("page","1");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        mModel.getBrandGoods(jo.toString()).subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Observer<BrandGoodsEntity>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(BrandGoodsEntity brandGoodsEntity) {
                        mRootView.success(brandGoodsEntity);
                    }

                    @Override
                    public void onError(Throwable e) {
                        mRootView.showMessage(e.getMessage());
                    }

                    @Override
                    public void onComplete() {

                    }
                });
    }
}

di package - > modules package

@Module
public class UploadModule {

    private UploadContract.IUploadView iUploadView;

    public UploadModule(UploadContract.IUploadView iUploadView) {
        this.iUploadView = iUploadView;
    }

    @ActivityScope
    @Provides
    public UploadContract.IUploadView  provideIView(){
        return iUploadView;
    }
    @ActivityScope
    @Provides
    public UploadContract.IUploadModel provideIModel(UploadModel model){
        return model;
    }

}
@Module
public class BrandGoodsModule {

    private BrandGoodsContract.IBrandGoodsView iBrandGoodsView;

    public BrandGoodsModule(BrandGoodsContract.IBrandGoodsView iBrandGoodsView) {
        this.iBrandGoodsView = iBrandGoodsView;
    }

    @ActivityScope
    @Provides
    public BrandGoodsContract.IBrandGoodsView providerIView(){
        return iBrandGoodsView;
    }
    @ActivityScope
    @Provides
    public BrandGoodsContract.IBrandGoodsModel providerIModel(BrandGoodsModel model){
        return model;
    }
}

di package - > component package

@ActivityScope
@Component(modules = UploadModule.class,dependencies = AppComponent.class)
public interface UploadComponent {
    void inject(MainActivity mainActivity);
}
@ActivityScope
@Component(modules = BrandGoodsModule.class,dependencies = AppComponent.class)
public interface BrandGoodsComponent {
    void inject(BrandGoodsActivity activity);
}

Rear hammer
view package - > activity package

public class MainActivity extends BaseActivity<UploadPresenter> implements UploadContract.IUploadView {

    @BindView(R.id.main_btn)
    Button btn;
    @Override
    public void success(UploadEntity entity) {
        Toast.makeText(this, entity.msg, Toast.LENGTH_SHORT).show();
    }

    @Override
    public void setupActivityComponent(@NonNull AppComponent appComponent) {
        DaggerUploadComponent.builder().appComponent(appComponent).uploadModule(new UploadModule(this)).build().inject(this);
    }

    @Override
    public int initView(@Nullable Bundle savedInstanceState) {
        return R.layout.activity_main;
    }

    @Override
    public void initData(@Nullable Bundle savedInstanceState) {
        ButterKnife.bind(this);
        mPresenter.upload(Environment.getExternalStorageDirectory().getAbsolutePath()+"/DCIM/Camera/tou2.png","1");
    }

    @Override
    public void showMessage(@NonNull String message) {
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    }

    @OnClick({R.id.main_btn})
    public void onClick(View view){
        int id = view.getId();
        if (id == R.id.main_btn){
            ARouter.getInstance().build("/model/BrandGoodsActivity").navigation();
        }
    }
}
@Route(path = "/model/BrandGoodsActivity")
public class BrandGoodsActivity extends BaseActivity<BrandGoodsPresenter> implements BrandGoodsContract.IBrandGoodsView {
    @BindView(R.id.brand_banner)
    Banner banner;
    ArrayList<String> imgUrl = new ArrayList<>();
    ArrayList<String> title = new ArrayList<>();
    @Override
    public void success(BrandGoodsEntity entity) {
        for (int i = 0; i < entity.banner.size(); i++){
            imgUrl.add("http://169.254.163.202/yoho"+entity.banner.get(i).recommend_url);
            title.add(entity.banner.get(i).recommend_name);
        }
        initBanner();
    }

    private void initBanner() {
        banner.setBannerStyle(BannerConfig.NUM_INDICATOR_TITLE);
        banner.setImages(imgUrl);
        banner.setBannerTitles(title);
        banner.setImageLoader(new ImageLoader() {
            @Override
            public void displayImage(Context context, Object path, ImageView imageView) {
                Glide.with(BrandGoodsActivity.this).load(path).into(imageView);
            }
        });
        banner.setDelayTime(2000);
        banner.start();
    }

    @Override
    public void setupActivityComponent(@NonNull AppComponent appComponent) {
        DaggerBrandGoodsComponent.builder().appComponent(appComponent).brandGoodsModule(new BrandGoodsModule(this)).build().inject(this);
    }

    @Override
    public int initView(@Nullable Bundle savedInstanceState) {
        return R.layout.brand_goods_layout;
    }

    @Override
    public void initData(@Nullable Bundle savedInstanceState) {
        ButterKnife.bind(this);
        mPresenter.getBrandGoods();
    }

    @Override
    public void showMessage(@NonNull String message) {

    }

}

appliocation

public class MyApplication extends BaseApplication {
    @Override
    public void onCreate() {
        super.onCreate();
        ARouter.openLog();
        ARouter.openDebug();
        ARouter.init(this);
    }
}

Keywords: ButterKnife Android Google Java

Added by pearjam on Fri, 09 Aug 2019 10:27:38 +0300