国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

# 對(duì) Android 應(yīng)用被強(qiáng)殺重回應(yīng)用的優(yōu)化處理(重走應(yīng)用流程)

2019-11-09 17:48:15
字體:
供稿:網(wǎng)友

關(guān)鍵詞:強(qiáng)殺 / home 鍵 / static 導(dǎo)致的 NullPointerException / BaseActivity

背景:Android 編程中我們經(jīng)常會(huì)使用到 static 變量,static 變量屬于類本身,所有實(shí)例調(diào)用的靜態(tài)變量的值都是一樣的,如果在某一個(gè)類里改變了一個(gè)靜態(tài)變量的值,其它所有的實(shí)例在調(diào)用這個(gè)值的時(shí)候也全都會(huì)發(fā)生了變化。static 在虛擬機(jī)中單獨(dú)占用內(nèi)存,在不同的包和類中都能使用,很方便。但是當(dāng)應(yīng)用被強(qiáng)殺后,若應(yīng)用較長(zhǎng)時(shí)間處于后臺(tái),會(huì)導(dǎo)致 NullPointerException 的異常產(chǎn)生。

解釋:因?yàn)榘聪?Android 的 home 鍵,如果位于后臺(tái)較長(zhǎng)時(shí)間,或者由于內(nèi)存不足應(yīng)用被強(qiáng)殺,應(yīng)用依然會(huì)保持 activity 的棧信息(activity 棧沒有被清空,比如說 A -> B -> C -> D 這個(gè)棧還保存了,只是 ABCD 這幾個(gè) activity 實(shí)例沒有了。所以回到 App 時(shí),顯示的還是 D 頁(yè)面),當(dāng)我們選擇 “最近打開的應(yīng)用” 回到前臺(tái)的時(shí)候,該 activity 會(huì)重新執(zhí)行 onCreate() 進(jìn)行初始化操作(也包括 application 的初始化),如果操作中包含了對(duì)其他類的靜態(tài)變量的引用,而應(yīng)用被強(qiáng)殺后該靜態(tài)變量的實(shí)例已被虛擬機(jī)回收,這樣便引發(fā)了空指針。 那么問題來了,我們理應(yīng)重新走應(yīng)用的流程,如何改善這種情況而避免這種異常的發(fā)生呢,既然 App 都被強(qiáng)殺了,干嘛不重新走第一次啟動(dòng)的流程呢,別讓 App 回到 D 而是再啟動(dòng) A,這樣所有的變量都是按正常的流程去初始化,也就不會(huì)空指針了。需要判斷是否被強(qiáng)殺,如果是,就強(qiáng)制重新走應(yīng)用的開始流程。通過在有心課堂的學(xué)習(xí),進(jìn)行了這個(gè)過程的模仿并梳理了思路。

參考:應(yīng)用被強(qiáng)殺了怎么辦 http://notes.stay4it.com/2016/02/26/how-to-handle-app-force-killed/

流程梳理 #

自定義了一個(gè) CustomApplication,用來初始化全局變量

public class CustomApplication extends Application { public static ArrayList<String> mTestNullPointer; // 我們把 -1 模擬表示被強(qiáng)殺 public static int mAppStatus = -1; @Override public void onCreate() { super.onCreate(); }}

做了一個(gè)父類 BaseActivity ,讓每一個(gè) Activity 都繼承自 BaseActivity,各 Activity 要么會(huì)執(zhí)行 PRotectApp() 方法,要么會(huì)執(zhí)行 setupData() 方法,前者是由于強(qiáng)殺,后者是正常情況下的初始化操作。

public class BaseActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 判斷如果被強(qiáng)殺,就回到 HomeActivity 中去,否則可以初始化 if (CustomApplication.mAppStatus == -1) { // 重走應(yīng)用流程 protectApp(); } else { setupData(); } } // 在這里做初始化操作 protected void setupData() { } // 使用 protected 讓子類可以重寫該方法 protected void protectApp() { // 重新走應(yīng)用的流程是一個(gè)正確的做法,因?yàn)閼?yīng)用被強(qiáng)殺了還保存 Activity 的棧信息是不合理的 Intent intent = new Intent(this, HomeActivity.class); intent.putExtra("action", "force_kill"); startActivity(intent); }}

下面是模擬強(qiáng)殺并且進(jìn)行優(yōu)化處理的做法流程

對(duì) Android 應(yīng)用被強(qiáng)殺重回應(yīng)用的優(yōu)化處理(重走應(yīng)用流程)

圖中各 Activity 對(duì)應(yīng)的代碼如下

1、WelcomeActivity

public class WelcomeActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { // 把狀態(tài)變?yōu)?0 能使父類不會(huì)走 protectApp() CustomApplication.mAppStatus = 0; super.onCreate(savedInstanceState); } @Override protected void setupData() { setContentView(R.layout.activity_welcome); handler.sendEmptyMessageDelayed(0, 1000); } Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); startActivity(new Intent(WelcomeActivity.this, LoginActivity.class)); finish(); } };}

2、LoginActivity

public class LoginActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); } public void login(View view) { startActivity(new Intent(this, HomeActivity.class)); }}

3、HomeActivity

/** * HomeActivity 的啟動(dòng)模式為 "singleTask" */public class HomeActivity extends BaseActivity implements View.OnClickListener { private Button mHomeProfileBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } // 初始化操作 @Override protected void setupData() { setContentView(R.layout.activity_home); mHomeProfileBtn = $(R.id.id_mHomeProfileBtn); mHomeProfileBtn.setOnClickListener(this); CustomApplication.mTestNullPointer = new ArrayList<>(); CustomApplication.mTestNullPointer.add("profile"); } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); String action = intent.getStringExtra("action"); if ("force_kill".equals(action)) { // 在 ProfileActivity 被強(qiáng)殺了就重新走應(yīng)用的流程 protectApp(); } } @Override protected void protectApp() { // 回到 WelcomeActivity startActivity(new Intent(this, WelcomeActivity.class)); finish(); } @Override public void onClick(View view) { startActivity(new Intent(this, ProfileActivity.class)); } @SuppressWarnings("unchecked") private <T> T $(int resId) { return (T) findViewById(resId); }}

4、ProfileActivity

public class ProfileActivity extends BaseActivity { private TextView mProfileLabel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 讓所有繼承于 BaseActivity 的子類的 onCreate() 都直接交給父類 BaseActivity 去操作, // 讓父類進(jìn)行一系列的先判斷,不讓子類隨隨便便地進(jìn)行初始化 } @Override protected void setupData() { setContentView(R.layout.activity_profile); mProfileLabel = $(R.id.id_mProfileLabel); mProfileLabel.setText(CustomApplication.mTestNullPointer.toString()); } @SuppressWarnings("unchecked") private <TT> TT $(int resId) { return (TT) findViewById(resId); }}

End.

Note by HF. Learn from 有心課堂



發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 开鲁县| 沙雅县| 松溪县| 莆田市| 汝南县| 平定县| 怀宁县| 文登市| 湟源县| 舟山市| 麻城市| 邵阳县| 郧西县| 黑山县| 滨州市| 闵行区| 灵寿县| 临沧市| 赤壁市| 白沙| 巴南区| 宣恩县| 营口市| 东台市| 马山县| 英吉沙县| 临湘市| 会昌县| 景洪市| 波密县| 广汉市| 新宁县| 民县| 西盟| 曲水县| 讷河市| 自治县| 高碑店市| 尚志市| 福清市| 明光市|