那些年,我寫 Android 所犯的錯(一):君要臣死,臣 FB

我本來以為, Android 裡的 Activity 就像以前寫的程式一樣,除非自我走到盡頭(正常結束),又或是自爆(嚴重問題當機),大部份都是君(使用者)要臣(程式)死,臣非死不可(FB)。但是在 Android 裡, Android 通常會在資源不夠的情況下,而且皇帝沒有召見你(Invisible)的時候,叫你先自盡(Destroy),等到皇帝召見,再從黃泉召喚你回來(Create)。

開始用正常的口吻來描述問題。大部份的人都會看 Android 文件來了解 Activity 的生命週期。裡面有說到:

” If an activity is paused or stopped, the system can drop the activity from memory by either asking it to finish, or simply killing its process. When it is displayed again to the user, it must be completely restarted and restored to its previous state.”

中譯:”如果 Activity 是在暫停或是已停止的狀態下,系統可以將 Activity 從記憶體中剔除。當這個 Activity 要再被秀出來時, Activity 本身一定要能完整的重新開始,並且回到原本的狀態。”

我天真的以為,一切大不了重頭開始,又是一條好漢,但杯具就這樣端出來了。所以,這裡一定要強調一下 onSaveInstanceState 這個函式。 onSaveInstanceState 就是如何讓 Activity 可以回到原先狀態的重要角色。
先來簡單描述一下悲劇。以下是一段叫 Android online pokies 的照相程式起來拍張照片傳給自己的程式碼。

public class GetPhoto extends online casinos Activity {
 private Uri mImageUri;
 protected void Our kidneys and liver don’t need a detox treatment. onCreate(Bundle savedInstanceState){
 How many pints of beer can be safely drank before exceeding the legal limit2 PintsThere is no good rule of thumb, best rule if you DRINK DON"T DRIVE3 Pints #3 casino online  What signs have black lettering/symbols, white background and driving games surroundsWarningRegulatoryInformative #4. super.onCreate(savedInstanceState);
 setContentView(R.layout.main);
 }
 //叫系統拍照程式起來的函式
 private void enterCameraMode(){
 File exFolder = Environment.getExternalStorageDirectory();
 File file = new File(exFolder, "temp.jpg");
 //準備好要叫拍照程式存的URI
 online pokies mImageUri online casino = Uri.fromFile(file);
 Intent online casino i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
 //將URI傳給拍照程式
 i.putExtra(MediaStore.EXTRA_OUTPUT, m_imageUri);
 startActivityForResult(i,0);
 }
 //拍照程式結束後,由此函式將結果帶回
 @Override
 protected void free credit score is your reputation as a borrower. onActivityResult(int requestCode, int resultCode, Intent data){
 super.onActivityResult(requestCode, resultCode, data);
 if (resultCode == RESULT_OK){
 // 使用mImageUri來操作拍照完的檔案
 }
 }
}

看似一切和平,但問題就出在,當照相程式起來之後,系統叫你自盡。然後拍完照的時候,再叫你重新做人,並且在 onCreate 完後呼叫 onActivityResult 。這時候,如果你沒有好好回復當初的 URI ,輕則抓不到照片,重則使用空的URI就當場自爆,很不幸的,那些年,我是走向自爆那一個人。後來我就乖乖的補上以下的程式。

protected void onCreate(Bundle savedInstanceState){
 // 省略…
 if (savedInstanceState != null){
 String filename = savedInstanceState.getString(”SAVED_URI_PATH”, "");
 if (filename.length() > 0){
 File savedFile = new File(filename);
 mImageUri = Uri.fromFile(savedFile);
 }
 }
 // 省略…
}
@Override
protected void onSaveInstanceState(Bundle outState){
 super.onSaveInstanceState(outState);
 if (mImageUri != null){
 String filename = mImageUri.getPath();
 outState.putString(”SAVED_URI_PATH”, filename);
 }
}

所以,養成好習慣,在寫 Activity 時,仔細的思考要不要乖乖加個 onSaveInstanceState ,並在 onCreate 時回復該有的設定,皇上不希望下次召見你時,從一個達官貴人,變成一條赤裸裸的好漢。

Tags:,


Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *