日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Android?Activity被回收的情況分析_Android

作者:發飆的蝸牛YR ? 更新時間: 2022-12-23 編程語言

1.onSaveInstanceState()方法

當一個Activity進入了停止狀態,是有可能被系統回收的。想象以下場景:應用中有一個ActivityA,用戶在ActivityA的基礎上啟動了ActivityB,ActivityA就進入了停止狀態,這個時候由于系統內存不足,將ActivityA回收掉了,然后用戶按下Back鍵返回ActivityA,會出現什么情況呢?其實還是會正常顯示ActivityA的,只不過這時并不會執行onRestart()方法,而是會執行ActivityA的onCreate()方法,因為ActivityA在這種情況下會被重新創建一次。

但是這種情況下可能會出現一個重要的問題:ActivityA中是可能存在臨時數據和狀態的。打個比方,MainActivity中如果有一個文本輸入框,現在你輸入了一段文字,然后啟動NormalActivity,這時MainActivity由于系統內存不足被回收掉,過了一會你又點擊了Back鍵回到MainActivity,這個時候你會發現剛剛輸入的文字都沒了,因為MainActivity被重新創建了。

如果我們的應用出現了這種情況是比較影響用戶體驗的,其實Activity還提供了一個onSaveInstanceState()回調方法,這個方法可以保證在Activity被回收之前一定會被調用,因此我們可以通過這個方法來解決這個問題。

onSaveInstanceState()方法會攜帶一個Bundle類型的參數,Bundle提供了一系列的方法保存數據,比如可以使用putString()方法保存字符串,使用putInt()方法保存整型數據,以此類推。每個保存方法需要傳入兩個參數,第一個參數是鍵,用于后面從Bundle中取值,第二個參數是真正要保存的內容。

在MainActivity中添加如下代碼就可以將臨時數據進行保存了:

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        val tempData="Something you just typed"
        outState.putString("data_key",tempData)
    }

數據是已經保存下來了,那么我們應該在哪里進行恢復呢?其實我們一直在使用的onCreate()方法其實也有一個Bundle類型的參數。這個參數在一般情況下都是null,但是如果在Activity被系統回收之前,你通過onSaveInstanceState()方法保存數據,這個參數就會帶有之前保存的全部數據,我們只需要再通過相應的取值方法將數據取出即可。

修改MainActivity的onCreate()方法,如下所示:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_first)
        if(savedInstanceState!=null){
            val tempData = savedInstanceState.getString("data_key")
            tempData?.let { Log.d("tag", it) }
        }
}

取出值之后就可以再做相應的恢復操作就可以了,比如將文本內容重新賦值到文本輸入框上,這里我只是簡單打印一下。

這里使用Bundle保存和取出數據和我們之前使用Intent傳遞數據的方法很類似,首先我們可以把需要傳遞的數據都保存在Bundle對象中,然后再將Bundle對象存放在Intent里。到了目標Activity之后,先從Intent中取出Bundle,再從Bundle中一一取出數據。

另外在手機的屏幕發生旋轉的時候,Activity也會經歷一個重新創建的過程,因而在這種情況下,Activity中的數據也會丟失。這種問題也可以通過onSaveInstanceState()方法來解決,但是對于橫豎屏已經有了更好的方案。

2.ViewModel

使用 ViewModel,我們就無需再用這種方法保存,因為 ViewModel 會自動感知生命周期,處理數據的保存與恢復。即數據可在發生屏幕旋轉等配置(其它例如分辨率調整、權限變更、系統字體樣式、語言變更等)更改后繼續留存。

代碼如下:

package com.example.viewmodeldemo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProvider;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
    private MyViewModel mMyViewModel;
    private TextView textView;
    private Button mButton1;
    private Button mButton2;
    private final String TAG="MainActivityTest";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate: ");
        //創建一個ViewModel對象
        mMyViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);
        textView=findViewById(R.id.textView);
        //ViewModel會保存數據,當你重新創建的時候會加載顯示出來
        textView.setText(String.valueOf(mMyViewModel.number));
        mButton1=findViewById(R.id.button1);
        mButton2=findViewById(R.id.button2);
        mButton1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mMyViewModel.number++;
                textView.setText(String.valueOf(mMyViewModel.number));
            }
        });
        mButton2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mMyViewModel.number+=2;
                textView.setText(String.valueOf(mMyViewModel.number));
            }
        });
    }
    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart: ");
    }
    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: ");
    }
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
    }
    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause: ");
    }
    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume: ");
    }
}
package com.example.viewmodeldemo;
import androidx.lifecycle.ViewModel;
//這里的ViewModel可以看作全局變量倉庫
public class MyViewModel extends ViewModel {
    public int number=0;
}

這樣當你旋轉屏幕生命周期發生變化,你的數據還在。

原文鏈接:https://blog.csdn.net/ChenYiRan123456/article/details/127600228

欄目分類
最近更新