編輯:關於Android編程
最近博主開始在項目中實踐MVP模式,卻意外發現內存洩漏比較嚴重,但卻很少人談到這個問題,促使了本文的發布,本文假設讀者已了解MVP架構。
MVP簡介
M-Modle,數據,邏輯操作層,數據獲取,數據持久化保存。比如網絡操作,數據庫操作
V-View,界面展示層,Android中的具體體現為Activity,Fragment
P-Presenter,中介者,連接Modle,View層,同時持有modle引用和view接口引用
示例代碼
Modle層操作
public class TestModle implements IModle{ private CallbackListener callback; public TestModle(CallbackListener callback) { this.callback = callback; } public interface CallbackListener { void onGetData(String data); } public void getData() { new Thread() { public void run() { callback.onGetData("返回的數據"); } }.start(); } }
View層
// 抽象的view層 public interface TestViewInterf extends IView { void onGetData(String data); } // 具體的View層 public class MainActivity extends Activity implements TestViewInterf{ private TestPresenter mTestPresenter; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // view層將獲取數據的任務委派給中介者presenter,並傳入自身實例對象,實現TestViewInterf接口 mTestPresenter = new TestPresenter(this); mTestPresenter.getData(); } @Override public void onGetData(String data) { // View層只做數據展示 showToast(data); } private void showToast(String toast) { Toast.makeText(this, toast, Toast.LENGTH_LONG).show(); } }
Presenter中介者
public class TestPresenter implements IPresenter{ IModle modle; IView view; public TestPresenter(IView view) { this.view = view; } public void getData() { // 獲取數據的操作實際在Modle層執行 modle = new TestModle(new CallbackListener() { public void onGetData(String data) { if (view != null) { view.onGetData(data); } } }); modle.getData(); } }
根據OOP思想,Java應面向接口編程,這樣才能給符合OCP原則。上述示例代碼省略了更加抽象的接口IModle,IView,IPresenter,並且實際MVP實踐中通常會引入泛型使其更具擴展性。
Google已提供了相關示例代碼,並在MVP中增加了一個約束者:Contract,它的作用是定義各個模塊的MVP接口。
google MVP sample code:https://github.com/googlesamples/android-architecture
內存洩露問題
由上可見,Presenter中持有View接口對象,這個接口對象實際為MainActivity.this,Modle中也同時擁有Presenter對象實例,當MainActivity要銷毀時,Presenter中有Modle在獲取數據,那麼問題來了,這個Activity還能正常銷毀嗎?
答案是不能!
當Modle在獲取數據時,不做處理,它就一直持有Presenter對象,而Presenter對象又持有Activity對象,這條GC鏈不剪斷,Activity就無法被完整回收。
換句話說:Presenter不銷毀,Activity就無法正常被回收。
解決MVP的內存洩露
Presenter在Activity的onDestroy方法回調時執行資源釋放操作,或者在Presenter引用View對象時使用更加容易回收的軟引用,弱應用。
比如示例代碼:
Activity
@Override public void onDestroy() { super.onDestroy(); mPresenter.destroy(); }
Presenter
public void destroy() { view = null; if(modle != null) { modle.cancleTasks(); } }
Modle
public void cancleTasks() { // TODO 終止線程池ThreadPool.shutDown(),AsyncTask.cancle(),或者調用框架的取消任務api }
個人總結
因為面向MVP接口編程,可適應需求變更,所以MVP適用於比較大的項目;因為其簡化了Activity和Fragmnt的職責,可大大減少View層的代碼量,比起MVC中Activity,Fragment動不動上千行的代碼量,簡直優雅!
做完以上操作,由於MVP引起的內存洩露就差不多解決了,以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
由於項目上的需要側滑條目展示收藏按鈕,記得之前代碼家有寫過一個厲害的開源控件 AndroidSwipeLayout 本來准備直接拿來使用,但是看過 issue 發現現在有
概述:當Android自帶的View滿足不了開發者時,自定義View就發揮了很好的作用。建立一個自定義View,需要繼承於View類,並且實現其中的至少一個構造函數和兩個
前言單點登錄SSO(Single Sign On)說得簡單點就是在一個多系統共存的環境下,用戶在一處登錄後,就不用在其他系統中登錄,也就是用戶的一次登錄能得到其他所有系統
最近在項目開發中,由於項目的需求要實現一些列表的單選,多選,全選,批量輸入之類的功能,其實功能的實現倒不是很復雜,需求中也沒有涉及到復雜的動畫什麼之類,主要是解決列表數據