XMVP(簡潔的MVP框架)

更新

v1.2.3-androidx 適配androixjava

v1.2.3 添加onPresenterCircle方法android

v1.2.2 Fragment懶加載數據,添加一些週期方法,修復一些buggit

v1.1.5 修復混淆後沒法建立presentergithub

v1.1.4 修復當前頁面的子類Activity因沒法建立presenter而崩潰的問題bash

v1.1.3 將Presenter中的star()方法放到了View的onInit()方法以後調用app

v1.1.2 XBasePresenter中添加判斷view是否還存在的方法框架

v1.1.1 添加擴展自v4包的Fragmentide

簡介

這是一個MVP框架,幫助項目快速的實現MVP結構。xmvp讓所寫的代碼更加簡潔,你無須在乎關係依賴問題,xmvp自動完成。這是繼《封了一個Android MVP框架,就叫XMVP吧!》後的一次大優化,因爲改動的比較多不便再次修改那篇文章,因此新開了這一篇。 使用xmvp能簡潔所寫代碼,使結構清晰,而且我也爲它開發了一套MVP管理插件,方便快速管理MVP代碼,在文章最後將稍做介紹。gradle

  • 在build.gradle中添加xmvp
dependencies {
    implementation 'com.github.xujiaji:xmvp:1.2.3-androidx'
}
複製代碼

使用androidx優化

dependencies {
    implementation 'com.github.xujiaji:xmvp:1.2.3-androidx'
}
複製代碼

項目地址:github.com/xujiaji/XMV…

如何使用?

只須要四部簡簡單單實現MVP結構

第一步:定義一個Contract

你須要定義一個Contract接口類,來抽象View、Presenter、Model的方法,而且它們須要分別繼承XContract.View、XContract.Presenter、XContract.Model接口。

例子:HomeContract

public interface HomeContract {
    interface Presenter extends XContract.Presenter{
        void loadData(Activity activity);
    }

    interface View extends XContract.View{
        void loadStart();
        void loadEnd(List<FileEntity> fileEntities);
    }

    interface Model extends XContract.Model {
        void scanFile(final Activity activity, final FileHelper.Listener<List<FileEntity>> listener);
    }
}
複製代碼

第二步:建立一個實現Model接口的實現類

例子:HomeModel

public class HomeModel implements HomeContract.Model {
    @Override
    public void scanFile(final Activity activity, final FileHelper.Listener<List<FileEntity>> listener) {
        new Thread() {
            @Override
            public void run() {
                final FileHelper fileHelper = new FileHelper();
                fileHelper.unzip(activity, listener);
            }
        }.start();
    }
}
複製代碼

第三步:建立一個實現Presenter接口的實現類,須要繼承XBasePresenter<T extends XContract.View, E extends XContract.Model>

注:

  • 泛型T:View接口
  • 泛型E:Model實現類
  • 在其中能夠直接使用viewmodel變量對View和Model進行操做。

例子: HomePresenter

public class HomePresenter extends XBasePresenter<HomeContract.View, HomeModel> implements HomeContract.Presenter {

    @Override
    public void loadData(Activity activity) {
        view.loadStart();
        model.scanFile(activity, new FileHelper.Listener<List<FileEntity>>() {
            @Override
            public void success(List<FileEntity> fileEntities) {
                view.loadEnd(fileEntities);
            }
        });
    }
}
複製代碼

第四步:建立一個實現View接口的實現類,這是一個Activity或者Fragment。須要繼承XBaseActivity<T extends XBasePresenter>XBaseFragment<T extends XBasePresenter>

注:

  • 泛型T:表示Presenter的實現類

例子: HomeActivity

public class HomeActivity extends XBaseActivity<HomePresenter> implements HomeContract.View {
    @BindView(R.id.toolbar)
    Toolbar toolbar;
    @BindView(R.id.rvFolder)
    RecyclerView rvFolder;
    @BindView(R.id.fragParentLayout)
    FrameLayout fragParentLayout;
    private ProgressDialog dialog;
    private HomeAdapter adapter;
    @BindView(R.id.appBarLayout)
    AppBarLayout appBarLayout;

    @Override
    protected void onInit() {
        super.onInit();
        ButterKnife.bind(this);
        toolbar.setTitle(R.string.xmvp_folder);
        setSupportActionBar(toolbar);
        rvFolder.setLayoutManager(new LinearLayoutManager(this));
        adapter = new HomeAdapter(new ArrayList<FileEntity>());
        rvFolder.setAdapter(adapter);
        presenter.loadData(this);
    }

    @Override
    protected void onListener() {
        super.onListener();
        adapter.setOpenLister(new HomeAdapter.OpenListener() {
            @Override
            public void open(File file) {
                showCode(file);
            }
        });

        toolbar.setNavigationOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onBackPressed();
            }
        });
    }

    /** * 顯示代碼 * * @param file */
    private void showCode(File file) {
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        CodeFragment cf = CodeFragment.newInstance(file);
        ft.replace(R.id.fragParentLayout, cf);
        ft.addToBackStack(null);
        ft.commit();
        showBlack(file.getName());
// rvFolder.setVisibility(View.GONE);
        fragParentLayout.setVisibility(View.VISIBLE);
    }

    /** * 顯示返回按鈕和標題,傳入null則隱藏返回按鈕 * @param title */
    private void showBlack(String title) {
        if (title != null) {
            toolbar.setNavigationIcon(R.drawable.ic_navigate_before_black_24dp);
            toolbar.setTitle(title);
            appBarLayout.setExpanded(true, true);
        } else {
            toolbar.setNavigationIcon(null);
            toolbar.setTitle(R.string.xmvp_folder);
            fragParentLayout.setVisibility(View.GONE);
        }

    }


    @Override
    public void loadStart() {
        dialog = new ProgressDialog(this);
        dialog.setTitle("正在加載數據");
        dialog.setCancelable(false);
        dialog.show();
    }

    @Override
    public void loadEnd(List<FileEntity> fileEntities) {
        if (dialog != null && dialog.isShowing()) {
            dialog.dismiss();
        }
        adapter.getData().addAll(fileEntities);
        adapter.notifyDataSetChanged();
    }

    @Override
    protected int getContentId() {
        return R.layout.activity_home;
    }

    @Override
    public void onBackPressed() {
        if (fragParentLayout.getVisibility() == View.VISIBLE) {
            showBlack(null);
        }
        super.onBackPressed();
    }
}
複製代碼

以上Home相關的類簡要關係圖

MVP UML


總結

就這麼的,只管實現和繼承。去掉上面的邏輯代碼後,總共就只需下面展現的代碼那麼點。

public interface HomeContract {
    interface Presenter extends XContract.Presenter{}
    interface View extends XContract.View{}
    interface Model extends XContract.Model {}
}

public class HomeModel implements HomeContract.Model {}

public class HomePresenter extends XBasePresenter<HomeContract.View, HomeModel> implements HomeContract.Presenter {}

public class HomeActivity extends XBaseActivity<HomePresenter> implements HomeContract.View {}
複製代碼

爲何不用手動添加依賴關係呢?由於在XBaseActivity中已經幫你實現了。 可是要確保3點:

  1. 抽象的接口必須對應繼承:XContract裏面的View、Presenter、Model接口。
  2. Presenter實現類必須以XBasePresenter<T extends XContract.View, E extends XContract.Model>爲父類,泛型T爲View抽象接口,泛型E爲Model實現類。
  3. View實現類以XBaseActivity<T extends XBasePresenter>XBaseFragment<T extends XBasePresenter>爲父類,泛型T爲Presenter的實現類。

提示:固然也能夠在如XBaseActivity這個類爲父類定義本身的BaseActivity,可參見:BaseActivity.java

據說你MVP代碼寫煩了?

告訴你一個好消息,有一個Android studio插件:它叫MVPManager,輕輕鬆鬆管理你的MVP代碼,讓你事半功倍。 簡單介紹一下MVPManager

  1. mvp編輯面板(經過右鍵module的包名 -> New -> MVPManager)
  • 給Contract命名
  • 選擇View所在包,輸入View的名稱,若是View存在則不會建立轉而直接添加View接口並實現接口中的方法。
  • 添加抽象的M、V、P方法。
  • 點擊OK將自動建立Contract,自動建立實現Contract中定義的View、Presenter、Model接口的實現類。
  • Contract在contract包中,View根據你的選擇,Presenter在presenter包中,Model在model包中。
  1. mvp修改面板(在對應的Contract類中右鍵 -> Generate -> MVPManager)
  • 可爲Model、View、Presenter添加方法或刪除方法,對於的實現類中也會進行添加方法或刪除方法。
  1. 已經上傳到JetBrains Plugin倉庫,能夠直接在intellij或Android studio裏面搜索MVPManager插件安裝了,詳細展現地址在下邊哦!

END

MVPManager:github.com/xujiaji/MVP…

xmvp:github.com/xujiaji/XMV…

Github:@xujiaji

相關文章
相關標籤/搜索