M:Model層,是那些javabean類,好比自定義的Person類等
V:View層,android裏的layout.xml文件
P:Presenter層,用來解耦網絡請求的,將網絡操做單獨放在這個P類裏java
public class MVCActivity extends AppCompatActivity {
private Button button;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
button = findViewById(R.id.button);
textView = findViewById(R.id.text_view);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new HttpModel(textView).request();
}
});
}
}
public class HttpModel {
private TextView textView;
public HttpModel(TextView textView) {
this.textView = textView;
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
textView.setText((String) msg.obj);
}
};
public void request() {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
Message msg = handler.obtainMessage();
msg.obj = "從網絡獲取到的數據";
handler.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
複製代碼
interface MVPView {
void updateTv(String text);
}
public class MVPActivity extends AppCompatActivity implements MVPView {
private Button button;
private TextView textView;
private Presenter presenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
button = findViewById(R.id.button);
textView = findViewById(R.id.text_view);
presenter = new Presenter(this);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
presenter.request();
}
});
}
@Override
public void updateTv(String text) {
textView.setText(text);
}
}
interface Callback {
void onResult(String text);
}
public class HttpModel {
private Callback callback;
public HttpModel(Callback callback) {
this.callback = callback;
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
callback.onResult((String) msg.obj);
}
};
public void request() {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
Message msg = handler.obtainMessage();
msg.obj = "從網絡獲取到的數據";
handler.sendMessage(msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
public class Presenter {
private MVPView view;
private HttpModel model;
public Presenter(MVPView view) {
this.view = view;
model = new HttpModel(new Callback() {
@Override
public void onResult(String text) {
Presenter.this.view.updateTv(text);
}
});
}
public void request() {
model.request();
}
}
複製代碼
P層:
public void detachView(){
view = null;
}
Activity:
@Override
protected void onDestroy(){
super.onDestroy();
presenter.detachView();
}
複製代碼
這裏分析下這個MVP開源庫:github.com/sockeqwe/mo… ,學習一下別人的思想,MVP是一種思想,但實際到項目中使用若是封裝好,用起來就會比較方便android
//這個MvpView接口咱們寫一個接口去繼承它,裏面提供通用更新View的方法,
//再讓業務Activity實現該接口,重寫對應方法,在方法中作相應的更新view的操做
public interface MvpView {
}
//P層對應有attachView() detachView() destroy() 三個通用方法
public interface MvpPresenter<V extends MvpView> {
/**
* Set or attach the view to this presenter
*/
@UiThread
void attachView(@NonNull V view);
/**
* Will be called if the view has been destroyed. Typically this method will be invoked from
* <code>Activity.detachView()</code> or <code>Fragment.onDestroyView()</code>
*
* @deprecated This method has been split into 2 methods: {@link #detachView()} and {@link #destroy()}
*/
@UiThread
@Deprecated
void detachView(boolean retainInstance);
/**
* Will be called if the view has been detached from the Presenter.
* Usually this happens on screen orientation changes or view (like fragment) has been put on the backstack.
*/
@UiThread
void detachView();
/**
* Will be called if the presenter is no longer needed because the View has been destroyed permanently.
* This is where you do clean up stuff.
*/
@UiThread
void destroy();
}
//來看下實現P層接口的通用Presenter類,主要分析下重寫的這三個方法
public class MvpBasePresenter<V extends MvpView> implements MvpPresenter<V> {
private WeakReference<V> viewRef;
private boolean presenterDestroyed = false;
@UiThread @Override public void attachView(V view) {
//傳進來的view是this,實現了V層接口的業務Activity,經過弱引用的方式進行
//引用,在Acitivy須要被回收的時候,Activity對象不會由於被弱引用引用而致使
//回收不了,防止內存泄漏
viewRef = new WeakReference<V>(view);
presenterDestroyed = false;
}
/**
* Gets the attached view. You should always call {@link #isViewAttached()} to check if the view
* is attached to avoid NullPointerExceptions.
* 在Presenter類中,經過此方法來獲取activity對象,調用對應的在activity
* 中重寫的更新view的方法,一般用法是:
* if(getView()!=null){ getView().updateView() }
*
* @return <code>null</code>, if view is not attached, otherwise the concrete view instance
* @deprecated Use {@link #ifViewAttached(ViewAction)}
*/
@Deprecated @UiThread public V getView() {
return viewRef == null ? null : viewRef.get();
}
/**
* {@inheritDoc}
*/
@Deprecated @UiThread @Override public void detachView(boolean retainInstance) {
}
/**
* {@inheritDoc}此方法也會在activity的onDestroy()中調用,同時還會在屏幕旋轉、
* Fragment的onDetachView()中調用
*/
@Override public void detachView() {
detachView(true);
if (viewRef != null) {
viewRef.clear();
viewRef = null;
}
}
/**
* {@inheritDoc} 此方法會在徹底退出即activty退出onDestroy()中使用
*/
@Override public void destroy() {
detachView(false);
presenterDestroyed = true;
}
}
複製代碼
public class ActivityMvpDelegateImpl<V extends MvpView, P extends MvpPresenter<V>>
implements ActivityMvpDelegate {
protected static final String KEY_MOSBY_VIEW_ID = "com.hannesdorfmann.mosby3.activity.mvp.id";
public static boolean DEBUG = false;
private static final String DEBUG_TAG = "ActivityMvpDelegateImpl";
private MvpDelegateCallback<V, P> delegateCallback;
protected boolean keepPresenterInstance;
protected Activity activity;
protected String mosbyViewId = null;
/**
* 這裏構造方法會傳進來三個參數,分別是activity,delegateCallback主要是構造Presenter,調用其createPresenter(),
* getPresenter(),setPresenter()方法,keepPresenterInstance判斷是否要保存Presenter實例
* @param activity The Activity
* @param delegateCallback The callback
* @param keepPresenterInstance true, if the presenter instance should be kept across screen
* orientation changes. Otherwise false.
*/
public ActivityMvpDelegateImpl(@NonNull Activity activity,
@NonNull MvpDelegateCallback<V, P> delegateCallback, boolean keepPresenterInstance) {
if (activity == null) {
throw new NullPointerException("Activity is null!");
}
if (delegateCallback == null) {
throw new NullPointerException("MvpDelegateCallback is null!");
}
this.delegateCallback = delegateCallback;
this.activity = activity;
this.keepPresenterInstance = keepPresenterInstance;
}
/**
* Determines whether or not a Presenter Instance should be kept
* 在onDestroy()中用於判斷是否保留Presenter實例
* @param keepPresenterInstance true, if the delegate has enabled keep
*/
static boolean retainPresenterInstance(boolean keepPresenterInstance, Activity activity) {
return keepPresenterInstance && (activity.isChangingConfigurations()
|| !activity.isFinishing());
}
/**
* Generates the unique (mosby internal) view id and calls {@link
* MvpDelegateCallback#createPresenter()}
* to create a new presenter instance
*
* @return The new created presenter instance
*/
private P createViewIdAndCreatePresenter() {
//這裏的createPresenter()最終是對應業務activity去重寫的,new出對應的Presenter
P presenter = delegateCallback.createPresenter();
if (presenter == null) {
throw new NullPointerException(
"Presenter returned from createPresenter() is null. Activity is " + activity);
}
//將對應activity和presenter保存
if (keepPresenterInstance) {
mosbyViewId = UUID.randomUUID().toString();
PresenterManager.putPresenter(activity, mosbyViewId, presenter);
}
return presenter;
}
@Override public void onCreate(Bundle bundle) {
P presenter = null;
if (bundle != null && keepPresenterInstance) {
mosbyViewId = bundle.getString(KEY_MOSBY_VIEW_ID);
if (DEBUG) {
Log.d(DEBUG_TAG,
"MosbyView ID = " + mosbyViewId + " for MvpView: " + delegateCallback.getMvpView());
}
if (mosbyViewId != null
&& (presenter = PresenterManager.getPresenter(activity, mosbyViewId)) != null) {
//
// Presenter restored from cache
//
if (DEBUG) {
Log.d(DEBUG_TAG,
"Reused presenter " + presenter + " for view " + delegateCallback.getMvpView());
}
} else {
//
// No presenter found in cache, most likely caused by process death
//
presenter = createViewIdAndCreatePresenter();
if (DEBUG) {
Log.d(DEBUG_TAG, "No presenter found although view Id was here: "
+ mosbyViewId
+ ". Most likely this was caused by a process death. New Presenter created"
+ presenter
+ " for view "
+ getMvpView());
}
}
} else {
// activity第一次啓動,須要建立對應presenter
// Activity starting first time, so create a new presenter
//
presenter = createViewIdAndCreatePresenter();
if (DEBUG) {
Log.d(DEBUG_TAG, "New presenter " + presenter + " for view " + getMvpView());
}
}
if (presenter == null) {
throw new IllegalStateException(
"Oops, Presenter is null. This seems to be a Mosby internal bug. Please report this issue here: https://github.com/sockeqwe/mosby/issues");
}
delegateCallback.setPresenter(presenter);
//持有對應activity的弱引用
getPresenter().attachView(getMvpView());
if (DEBUG) {
Log.d(DEBUG_TAG, "View" + getMvpView() + " attached to Presenter " + presenter);
}
}
private P getPresenter() {
P presenter = delegateCallback.getPresenter();
if (presenter == null) {
throw new NullPointerException("Presenter returned from getPresenter() is null");
}
return presenter;
}
private V getMvpView() {
V view = delegateCallback.getMvpView();
if (view == null) {
throw new NullPointerException("View returned from getMvpView() is null");
}
return view;
}
@Override public void onDestroy() {
boolean retainPresenterInstance = retainPresenterInstance(keepPresenterInstance, activity);
//釋放activiy的弱引用
getPresenter().detachView();
if (!retainPresenterInstance){
getPresenter().destroy();
}
if (!retainPresenterInstance && mosbyViewId != null) {
PresenterManager.remove(activity, mosbyViewId);
}
if (DEBUG) {
if (retainPresenterInstance) {
Log.d(DEBUG_TAG, "View"
+ getMvpView()
+ " destroyed temporarily. View detached from presenter "
+ getPresenter());
} else {
Log.d(DEBUG_TAG, "View"
+ getMvpView()
+ " destroyed permanently. View detached permanently from presenter "
+ getPresenter());
}
}
}
@Override public void onPause() {
}
@Override public void onResume() {
}
@Override public void onStart() {
}
@Override public void onStop() {
}
@Override public void onRestart() {
}
@Override public void onContentChanged() {
}
@Override public void onSaveInstanceState(Bundle outState) {
if (keepPresenterInstance && outState != null) {
outState.putString(KEY_MOSBY_VIEW_ID, mosbyViewId);
if (DEBUG) {
Log.d(DEBUG_TAG,
"Saving MosbyViewId into Bundle. ViewId: " + mosbyViewId + " for view " + getMvpView());
}
}
}
@Override public void onPostCreate(Bundle savedInstanceState) {
}
}
複製代碼
public abstract class MvpActivity<V extends MvpView, P extends MvpPresenter<V>>
extends AppCompatActivity implements MvpView,
com.hannesdorfmann.mosby3.mvp.delegate.MvpDelegateCallback<V,P> {
protected ActivityMvpDelegate mvpDelegate;
protected P presenter;
protected boolean retainInstance;
@Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getMvpDelegate().onCreate(savedInstanceState);
}
@Override protected void onDestroy() {
super.onDestroy();
getMvpDelegate().onDestroy();
}
@Override protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
getMvpDelegate().onSaveInstanceState(outState);
}
@Override protected void onPause() {
super.onPause();
getMvpDelegate().onPause();
}
@Override protected void onResume() {
super.onResume();
getMvpDelegate().onResume();
}
@Override protected void onStart() {
super.onStart();
getMvpDelegate().onStart();
}
@Override protected void onStop() {
super.onStop();
getMvpDelegate().onStop();
}
@Override protected void onRestart() {
super.onRestart();
getMvpDelegate().onRestart();
}
@Override public void onContentChanged() {
super.onContentChanged();
getMvpDelegate().onContentChanged();
}
@Override protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
getMvpDelegate().onPostCreate(savedInstanceState);
}
/**
* Instantiate a presenter instance
* 讓繼承MvpActivity的業務Activity重寫此方法,new出對應的Presenter對象
* @return The {@link MvpPresenter} for this view
*/
@NonNull public abstract P createPresenter();
/**
* Get the mvp delegate. This is internally used for creating presenter, attaching and detaching
* view from presenter.
*
* <p><b>Please note that only one instance of mvp delegate should be used per Activity
* instance</b>.
* </p>
*
* <p>
* Only override this method if you really know what you are doing.
* </p>
*
* @return {@link ActivityMvpDelegateImpl}
*/
@NonNull protected ActivityMvpDelegate<V, P> getMvpDelegate() {
if (mvpDelegate == null) {
mvpDelegate = new ActivityMvpDelegateImpl(this, this, true);
}
return mvpDelegate;
}
@NonNull @Override public P getPresenter() {
return presenter;
}
@Override public void setPresenter(@NonNull P presenter) {
this.presenter = presenter;
}
@NonNull @Override public V getMvpView() {
return (V) this;
}
}
複製代碼