android中MVP模式

释放双眼,带上耳机,听听看~!

我们之前在项目中都是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) {
}
}

人已赞赏
Android文章

Android圆角ViewGrup/View库(可加边框),妈妈再也不用担心设计圆角了!

2020-2-23 20:10:37

Android文章

android动画 补间动画(Tween Animation)

2020-2-23 22:30:13

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索