android开发技巧安卓开发

android中MVP模式

2019-12-27  本文已影响0人  wervy

我们之前在项目中都是MVC模式,网络请求和展示数据都是在Activity页面上,比如像:

/**
 * Created by sww on 16/6/16.
 */
public class AudioActivity extends FragmentActivity implements View.OnClickListener {

    private RecyclerView rvAudio;

    private String isbn;
    private String bookName;
    private String officialAudioUrl;
    private String bookImgUrl;
    private int recordPageNo = 1;
    private int sortType = 0;
    private boolean isFirstTime = true;
    private AudioAdapter audioAdapter;
    private LoadMoreRecyclerViewAdapter audioLoadMoreRecyclerViewAdapter;

    private static final int PAGE_SIZE = 10;
    private ArrayList<UserAudio> userAudioArrayList = new ArrayList<UserAudio>();
    public static final String ISBN = "isbn";
    public static final String BOOK_NAME = "book_name";
    public static final String OFFICIAL_AUDIO_URL = "official_audio_url";
    public static final String BOOK_IMG_URL = "book_img_url";

    private static final String GET_AUDIO_URL = "taleteling/get-list";
    private static final String ADD_AUDIO_PLAY_COUNT = "taleteling/play";
    private static final String AUDIO_LIKE_URL = "taleteling/like";
    private static final String TAG = "AudioActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_audio);
        isbn = getIntent().getStringExtra(ISBN);
        bookName = getIntent().getStringExtra(BOOK_NAME);
        officialAudioUrl = getIntent().getStringExtra(OFFICIAL_AUDIO_URL);
        bookImgUrl = getIntent().getStringExtra(BOOK_IMG_URL);
        initView();
        getRecordData(AudioActivity.this, sortType, false);
    }

    private void initView() {
        RelativeLayout rlAudioTitle = (RelativeLayout) findViewById(R.id.rl_audio_title);
        rlAudioTitle.setOnClickListener(this);
        ImageButton backImg = (ImageButton) findViewById(R.id.btn_back);
        backImg.setOnClickListener(this);
        ImageView recordImg = (ImageView) findViewById(R.id.record_img);
        recordImg.setOnClickListener(this);
        rvAudio = (RecyclerView) findViewById(R.id.rv_audio);
        rvAudio.setLayoutManager(new LinearLayoutManager(this));

        initRecyclerView(rvAudio);

        audioAdapter.setOnChangeDataListener(new AudioAdapter.OnChangeDataListener() {
            @Override
            public void onChangeData(int sortType) {
                changeDataSource(sortType);
            }

            @Override
            public void onAddAudioPlayCount(int audioNo) {
                addAudioPlayCount(AudioActivity.this, audioNo);
            }

            @Override
            public void onLikeAudio(UserAudio userAudio, int position) {
                audioLike(AudioActivity.this, userAudio, position);
            }
        });
    }

    private void initRecyclerView(RecyclerView recyclerView) {
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);
        recyclerView.setHasFixedSize(true);
        audioAdapter = new AudioAdapter(AudioActivity.this, officialAudioUrl, bookImgUrl, userAudioArrayList, true);
        audioLoadMoreRecyclerViewAdapter = new LoadMoreRecyclerViewAdapter(this, audioAdapter,
                new LoadMoreRecyclerViewAdapter.RequestToLoadMoreListener() {
                    @Override
                    public void onAfterLoadMoreRequested() {
                        if (isFirstTime) {
                            isFirstTime = false;
                        } else {
                            Utils.TLog(TAG, "audio onAfterLoadMoreRequested");
                            getRecordData(AudioActivity.this, sortType, true);
                        }
                    }

                    @Override
                    public void onBeforeLoadMoreRequested() {

                    }
                });
        recyclerView.setAdapter(audioLoadMoreRecyclerViewAdapter);
    }

    private void changeDataSource(int sortType) {
        this.sortType = sortType;
        getRecordData(AudioActivity.this, sortType, false);
    }

    private void getRecordData(final Context context, int sortType, final boolean getMore) {
        String currentTime = String.valueOf(Utils.getCurrentTimeMillis());
        HashMap<String, String> hashMap = new HashMap<String, String>();
        hashMap.put("time", currentTime);
        hashMap.put("ISBN", isbn);
        hashMap.put("SortType", String.valueOf(sortType));
        recordPageNo = getMore ? recordPageNo + 1 : 1;
        hashMap.put("PageIndex", String.valueOf(recordPageNo));
        hashMap.put("PageSize", String.valueOf(PAGE_SIZE));
        com.google.gson.JsonObject jsonObject = RequestUtil.generateRequestJson(hashMap);
        List<NameValuePair> nameValuePairs = RequestUtil.generateRequestNameValuePair(hashMap);

        ApiClient.postBusinessWithToken(context, GET_AUDIO_URL, nameValuePairs, jsonObject, currentTime, new TextHttpResponseHandler() {

            @Override
            public void onSuccess(int statusCode, Header[] headers, String responseString) {
                Utils.TLog(TAG + "---getRecordData---", responseString);
                try {
                    JSONObject response = new JSONObject(responseString);
                    String responseCode = response.getString(RequestUtil.RESPONSE_CODE);
                    String message = response.getString(RequestUtil.RESPONSE_MESSAGE);
                    if (responseCode.equals(RequestUtil.RESPONSE_CORRECT_CODE)) {
                        if (!getMore) {
                            userAudioArrayList.clear();
                        }
                        if (!response.getString(RequestUtil.RESPONSE_RESULT).equals(RequestUtil.RESPONSE_RESULT_NULL)) {
                            JSONObject jsonObject = response.getJSONObject(RequestUtil.RESPONSE_RESULT);
                            parseAudioJson(jsonObject);
                            audioAdapter.notifyDataSetChanged();
                            JSONArray jsonArray = jsonObject.getJSONArray("TValues");
                            audioLoadMoreRecyclerViewAdapter.onDataReadyAfter(jsonArray.length() >= PAGE_SIZE);
                        } else {
                            audioLoadMoreRecyclerViewAdapter.onDataReadyAfter(false);
                        }
                    } else {
                        Utils.ToastError(context, message);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
                Utils.TLog(TAG, responseString);
                audioLoadMoreRecyclerViewAdapter.onDataReadyAfter(false);
            }
        });
    }

    private void parseAudioJson(JSONObject jsonObject) {
        try {
            JSONArray jsonArray = jsonObject.getJSONArray("TValues");
            int length = jsonArray.length();
            for (int i = 0; i < length; i++) {
                UserAudio userAudio = new UserAudio();
                JSONObject userAudioJson = jsonArray.getJSONObject(i);
                userAudio.setUserAudioNo(userAudioJson.optInt("SysNo"));
                userAudio.setPlayCount(userAudioJson.optInt("PlayCount"));
                userAudio.setLikeCount(userAudioJson.optInt("LikeCount"));
                userAudio.setIsLiked(userAudioJson.optBoolean("Liked"));
                userAudio.setRank(userAudioJson.optInt("Ranking"));
                userAudio.setUserNickName(userAudioJson.optString("UserNickName"));
                userAudio.setISBN(userAudioJson.optString("BookISBN"));
                userAudio.setBookName(userAudioJson.optString("BookName"));
                userAudio.setUserHeadPicUrl(userAudioJson.optString("UserPortrait"));
                userAudio.setIsSelfAudio(userAudioJson.optBoolean("SelfFlag"));
                userAudio.setBookImgUrl(userAudioJson.optString("BookFrontCover"));
                userAudio.setAudioTitle(userAudioJson.optString("Title"));
                userAudio.setAudioDes(userAudioJson.optString("Description"));
                userAudio.setAudioCreateDate(userAudioJson.optLong("CreateDate"));
                userAudio.setAudioTime(userAudioJson.optInt("RecordingDate"));
                userAudio.setAudioTime(userAudioJson.optInt("RecordingDate"));
                List<String> audioList = new ArrayList<String>();
                JSONArray audioArray = userAudioJson.getJSONArray("AudioList");
                int audioLength = audioArray.length();
                for (int j = 0; j < audioLength; j++) {
                    audioList.add(audioArray.optString(j));
                }
                userAudio.setAudioUrlList(audioList);
                userAudioArrayList.add(userAudio);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private void addAudioPlayCount(final Context context, int audioNo) {
        String currentTime = String.valueOf(Utils.getCurrentTimeMillis());
        HashMap<String, String> hashMap = new HashMap<String, String>();
        hashMap.put("time", currentTime);
        hashMap.put("SysNo", String.valueOf(audioNo));
        com.google.gson.JsonObject jsonObject = RequestUtil.generateRequestJson(hashMap);
        List<NameValuePair> nameValuePairs = RequestUtil.generateRequestNameValuePair(hashMap);

        ApiClient.postBusinessWithToken(context, ADD_AUDIO_PLAY_COUNT, nameValuePairs, jsonObject, currentTime, new TextHttpResponseHandler() {

            @Override
            public void onSuccess(int statusCode, Header[] headers, String responseString) {
                //增加播放次数的请求不处理返回结果
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
                Utils.TLog(TAG, responseString);
            }
        });
    }

    private void audioLike(final Context context, final UserAudio userAudio, final int position) {
        String currentTime = String.valueOf(Utils.getCurrentTimeMillis());
        HashMap<String, String> hashMap = new HashMap<String, String>();
        hashMap.put("time", currentTime);
        hashMap.put("SysNo", String.valueOf(userAudio.getUserAudioNo()));
        com.google.gson.JsonObject jsonObject = RequestUtil.generateRequestJson(hashMap);
        List<NameValuePair> nameValuePairs = RequestUtil.generateRequestNameValuePair(hashMap);

        ApiClient.postBusinessWithToken(context, AUDIO_LIKE_URL, nameValuePairs, jsonObject, currentTime, new TextHttpResponseHandler() {

            @Override
            public void onSuccess(int statusCode, Header[] headers, String responseString) {
                try {
                    JSONObject response = new JSONObject(responseString);
                    String responseCode = response.getString(RequestUtil.RESPONSE_CODE);
                    if (responseCode.equals(RequestUtil.RESPONSE_CORRECT_CODE)) {
                        if (response.getString(RequestUtil.RESPONSE_RESULT).equals(RequestUtil.RESPONSE_RESULT_TRUE)) {
                            Utils.ToastSuccess(AudioActivity.this, "点赞成功");
                            userAudio.setIsLiked(true);
                            int likeCount = userAudio.getLikeCount();
                            userAudio.setLikeCount(likeCount + 1);
                            audioAdapter.notifyItemChanged(position);
                        }
                    } else {
                        String message = response.getString(RequestUtil.RESPONSE_MESSAGE);
                        Utils.ToastError(AudioActivity.this, message);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onFailure(int statusCode, Header[] headers, String responseString, Throwable throwable) {
                Utils.TLog(TAG, responseString);
            }
        });
    }

    private void startBookRecord() {
        Intent intent = new Intent();
        intent.putExtra(RecordActivity.BOOKISBN, isbn);
        intent.putExtra(RecordActivity.BOOKNAME, bookName);
        intent.putExtra(RecordActivity.BOOKPICURL, bookImgUrl);
        intent.setClass(this, RecordActivity.class);
        startActivity(intent);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        audioAdapter.audioPlayer.stop();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_back:
                finish();
                break;
            case R.id.record_img:
                startBookRecord();
                break;
            case R.id.rl_audio_title:
                rvAudio.smoothScrollToPosition(0);
                break;
            default:
                break;
        }
    }
}

这样显得Activity代码特别多,看起来很头痛,维护起来很麻烦

为什么在项目使用MVP模式,当然是它有很多优点

1 代码层次分明

2 view和Model分开,便于维护

使用MVP模式,代码结构如下:


image.png

先封装几个Base类

BaseView
public interface BaseView {

    /**
     * UI 业务逻辑,加载Loading
     */
    void showLoading();
    void hideLoading();
}

BasePersenter
/**
 * T 对应着Activity的UI抽象接口 视图
 * @param <V>
 */
public abstract class BasePersenter<V> {

    protected WeakReference<V> mViewRef; //iew持有activity的引用,防止内存泄漏,使用弱引用

    public abstract void fectch();

    public void attachView(V view){
        mViewRef = new WeakReference<>(view);
        Log.i("++++++++-------attach","" + mViewRef.get());
    }

    /**
     * 解绑
     */
    public void detach(){
        Log.i("++++++++-------detach","" + mViewRef.get());
        if (mViewRef != null){
            mViewRef.clear();
            mViewRef = null;
        }
    }
}

BaseActivity

public abstract class BaseActivity<V, T extends BasePersenter<V>> extends AppCompatActivity {

    protected T mPresent;
    protected FontIconView backIcon;

    public enum Status {
        NAVIGATION, STATUS, Default
    }

    @Override
    protected void onCreate( Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.i("-------","-------onCreate");
        backIcon = (FontIconView) findViewById(R.id.back_font);
        mPresent = createPresent();
        mPresent.attachView((V) this);
//        setStatusBar(getStatusBarColor());
        if (backIcon != null) {
            backIcon.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    onBackPressed();
                }
            });
        }
    }
    /**
     * Android 6.0 以上设置状态栏颜色
     */
    protected void setStatusBar(@ColorInt int color) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            // 设置状态栏底色颜色
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
            getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
            getWindow().setStatusBarColor(color);

            // 如果亮色,设置状态栏文字为黑色
            if (isLightColor(color)) {
                getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
            } else {
                getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
            }
        }

    }

    /**
     * 判断颜色是不是亮色
     *
     * @param color
     * @return
     */
    private boolean isLightColor(@ColorInt int color) {
        return ColorUtils.calculateLuminance(color) >= 0.5;
    }

    /**
     * 获取StatusBar颜色,默认白色
     *
     * @return
     */
    protected @ColorInt
    int getStatusBarColor() {
        return getResources().getColor(R.color.white);
    }


    protected abstract T createPresent();
}

一个模块中View层代码

interface DcOrderListView {
    fun success(list: List<DcOrderListBean>)
    fun fail(result: String)
}

一个模块中Model层代码

interface IDcActivityListListener<T> {


    fun  success(t:T)
    fun fail(result:String)
}
interface IDcActivityList<T> {

    fun loadListData(context: Context, paramsUtil: RequestBody, listener: IDcActivityListListener<T>)


}
Model层的实现类
class DcOrderListImpl:IDcActivityList<List<DcOrderListBean>> {



    override fun loadListData(context: Context, paramsUtil: RequestBody, listener: IDcActivityListListener<List<DcOrderListBean>>) {

        DcApiLoader(context).agentCoreServiceFind(paramsUtil,object :Observer<CommonBean<List<DcOrderListBean>>>{
            override fun onComplete() {
            }

            override fun onSubscribe(d: Disposable) {
            }

            override fun onNext(t: CommonBean<List<DcOrderListBean>>) {

                if (ActivityConstant.BLYA_SUCCESS_CODE.equals(t.code)){
                    listener.success(t.data)
                }else {
                    listener.fail(t.message)
                }

            }

            override fun onError(e: Throwable) {

                listener.fail("系统异常")
            }

        })

    }
}

P层代码

class DcOrderListPresenter(dcOrderListView: DcOrderListView): BasePersenter<DcOrderListView>() {

    var viewModel = DcOrderListImpl()
    var dcOrderListView = dcOrderListView

    override fun fectch() {
        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
    }

    fun loadData(context: Context, param: RequestBody){
        viewModel.loadListData(context,param,object : IDcActivityListListener<List<DcOrderListBean>>{
            override fun success(t: List<DcOrderListBean>) {

                dcOrderListView.success(t)
            }

            override fun fail(result: String) {

                dcOrderListView.fail(result)

            }

        })
    }


}
Activity的代码,就简介多了
class MyDcActivity : BaseActivity<DcOrderListView,DcOrderListPresenter>(),DcOrderListView {

    private lateinit var titleText:TextView
    private lateinit var recyclerView: RecyclerView
    private lateinit var dcOrderListPresenter: DcOrderListPresenter
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_my_dc)
        initView()
    }

    private fun initView(){

        titleText = findViewById(R.id.title_text) as TextView
        recyclerView = findViewById(R.id.recycleView) as RecyclerView
        titleText.text = "我的代采"

    }

     @RequiresApi(Build.VERSION_CODES.KITKAT)
    private fun initData(){

        var map = ArrayMap<String,String>()
        map["page"] = "1"
        map["limit"] = "10"

        var util = NetParamsUtil(map)
        presenter.agentFind(this,util.param())

    }

    override fun createPresent(): DcOrderListPresenter {

        dcOrderListPresenter = DcOrderListPresenter(this)
        return dcOrderListPresenter
    }

    override fun success(list: List<DcOrderListBean>) {


    }

    override fun fail(result: String) {


    }


}
上一篇 下一篇

猜你喜欢

热点阅读