ActivityベースクラスはBundleデータの保存を実現し、空のポインタと重複労働を避ける

4727 ワード

初心者に話す言葉


Androidの開発経験があると信じている友人は多かれ少なかれActivityの一部のオブジェクトに不思議な空のポインタの異常に遭遇したことがある.この異常は通常、Activityがバックグラウンドに切り替えられ、ゲームをしたり、他のアプリケーションを開いたりするなど、メモリのオーバーヘッドが大きいことがあります.バックグラウンドにあるため、このActivityの優先度が低下し、メモリがきついときに回収される可能性が高い.まだこのメカニズムに慣れていない友达はここでいくつかの問題に直面するかもしれません.
メモリは回収されたが,コードトリガの動作ではなくシステムの決定であるため,ユーザがこのアプリケーションを再起動すると,起動プロセスを再開するのではなく,離れた時点のActivityに戻る.またActivityはすでに回収されているので、当然ながらonCreateからのライフサイクルを再作成し、再実行します.
この場合、Androidには、onSaveInstanceState、onRestoreInstanceStateというライフサイクルのペアがあり、Activityを回収される前の状態に保存して取り出すために使用されます.詳細は、以下を参照してください.http://blog.csdn.net/initphp/article/details/11973651

本文


onSaveInstanceState、onRestoreInstanceStateは本当にすべての問題を解決できますか?
@Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
    super.onCreate(savedInstanceState, persistentState);
    Data data = getIntent().getParcelableExtra("data");
    if (data.type == 0) {
        setContentView(R.layout.activity_to);
        //TODO
    } else {
        setContentView(R.layout.activity_from);
        //TODO
    }
}

以上のコードの意図は明確で,前のインタフェースから伝達されたパラメータdataのtypeに基づいてどのレイアウトをロードするかを決定する.このコードが不合理なのはともかく、この光景でメモリが回収されたら何が起こるか考えてみると面白い.
1.getIntent()は、前のインタフェースから渡されたbundleデータを取得できません.この場合、dataオブジェクトは必ず空になります.2.onRestoreInstanceStateの実行タイミングはonCreateの後です.つまり、onCreateのライフサイクルでgetIntent()メソッドで前のインタフェースから渡されたパラメータを取得し、すぐに使用すると、onRestoreInstanceStateはまだ呼び出されていません.3.空のポインタがT_を呼び出すT
So ?
私はそうしました
@Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
   super.onCreate(savedInstanceState, persistentState);
   
   if (savedInstanceState == null) {
       data = getIntent().getParcelableExtra("data");
   } else {
       data = savedInstanceState.getParcelable("data");
   }
   
   if (data.type == 0) {
       setContentView(R.layout.activity_to);
       //TODO
   } else {
       setContentView(R.layout.activity_from);
       //TODO
   }
}

savedInstanceStateは保存されているActivityの状態で、nullの場合は正常にアクセスし、そうでない場合はメモリが回収されて再起動されることを考慮します.
このコードは、状況に応じてgetIntent()またはsavedInstancesStateからdataオブジェクトを取得します.もちろん、前提条件は私がこのようにしていることです.
@Override
protected void onSaveInstanceState(Bundle outState) {
   outState.putParcelable("data", data);
   super.onSaveInstanceState(outState);
}

すなわち、回収される前にdataオブジェクトをbundleに保存します.
全体的には簡単に見えますよね?私はNullPointerの苦海を離れてよかったが、これは苦難の始まりにすぎない.T

真·本文


実際の開発ではbundleにdataというパラメータが1つしかないとは限らず、いくつかのパラメータがある場合もよくあり、上記のコードが拡張されます.
コードライン数は、パラメータ数*2(取)+パラメータ数*1(存)にほぼ等しい
つまり、伝達パラメータを1つ増やすたびに、私は3行のコードを多く書き、栄養価のない3行のコードを書きます.これは第1層の意味での繰り返し労働である.
それから、Bundleパラメータを受信するActivityごとに、私はこのようないくつかのコードを書きます.論理は基本的に完全に同じで、これは第2層の意味での繰り返しです.
沈黙の中で爆発しなければ、沈黙の中で滅びるという言葉がある.ついにある日私は我慢できなくて、どのように更に优しくこの问题を解决することができますかを考え始めました.
Activityごとに同じ論理コードを書くのを避けるには、まずベースクラスに書くことを考えます.
private Bundle savedBundle;

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   initBundle(savedInstanceState);
   initData(savedBundle);
}

onCreateメソッドでは親メソッドを実行する以外にinitBundleとinitDataの2つのメソッドしか実行されていないことがわかります.
/**
*   onCreate   bundle, 
*   null,  activity   bundle
* @param savedInstanceState
*/
private void initBundle(Bundle savedInstanceState) {
   if (savedInstanceState == null) {
       savedBundle = getIntent().getExtras();
   } else {
       savedBundle = savedInstanceState.getBundle("savedBundle");
   }

   // ,  savedBundle,  null pointer
   if (savedBundle == null) {
       savedBundle = new Bundle();
   }
}

/**
*   bundle
* @param outState
*/
protected void onSaveInstanceState(Bundle outState) {
   outState.putBundle("savedBundle", this.savedBundle);
   super.onSaveInstanceState(outState);
}

前の処理方法と似ていますか?唯一の違いはgetIntent()の時、私はすべてのデータを取り出してsavedBundleに値を付けて、保存する時もsavedBundleというオブジェクトだけを保存します.
私は新しいデータを生産していません.私はただデータの運搬工です.
ところで、もう一つのinitDataの方法は何ですか?
/**
*  
* @param savedBundle
*/
protected void initData(Bundle savedBundle) {

}

何もしていなかったのか.の

How to use ?


ベースクラスから引き継いだActivityではinitDataメソッドを上書きすればよい
@Override
protected void initData(Bundle savedBundle) {
   super.initData(savedBundle);
   int data = savedBundle.getInt("data");
   Log.i("bundle", " data =  " + data);
}

どのようなパラメータがinitDataメソッドから提供されたsavedBundleから直接取り出され、安全で汚染がなく、省力で安心します.

後記


実は技術の含有量がなくて、私自身もあまりすごい技術が吹聴することができません.しかし、最初のNull Pointerと比べると、Null Pointerを処理するために何度も繰り返し仕事をするより、ずっといいのではないでしょうか.