最近やっていたAndroid案件で、メモリリーク対策についてまた理解が進んだのでメモ。
主要な参考先:
http://tomokey.blogspot.jp/2011/05/android.html
コツ:
■内部クラスは static にする。
■「弱参照」という仕組みについて理解して、アクティビティやフラグメントといったライフサイクルのあるインスタンスを他のクラスに保持させるときはこの弱参照を使う。
■内部クラスから外側クラスにアクセスする必要がある場合、内部クラスのプロパティに外側クラスのインスタンスを持たせて、内部クラスのコンストラクタで外側クラスのインスタンスを渡す。この時、弱参照インスタンスとして保持しておく。
■処理の効率化のために作成した色々なクラスでも、プロパティにアクティビティやフラグメントを保持するときは弱参照経由にしておく。
■あとは、とにかくフラグメントやアクティビティを遷移するときは古いインスタンスを初期化していく。onResume()で準備したインスタンスはonPause()で片付けて、onStart()で準備したインスタンスはonStop()で片付ける。
---------------------------------
弱参照について。
通常、あるインスタンスへの参照を作成すると、それは「強参照」という強い参照になるらしい。
弱参照というのは弱い参照で、ガベージコレクションの対象になりやすい。
あるインスタンスについて、参照がひとつでも残っているとガベージコレクションの対象にならないという。
しかし、あるインスタンスについて、そこに残っている参照が弱参照のみだったら、それはGCの対象になるという。
アクティビティやフラグメントなど、ライフサイクルを持つものは、開発者が意図してないタイミングで破棄されたり再生成されたりするらしい。
しかしそうやってこっそり破棄された時、そのアクティビティやフラグメントへの参照(強参照)が残っていると、きちんと破棄されないでメモリを圧迫するという。
なので、これらへの参照は弱参照がいいのだということだ。
例:フラグメントクラスでアクティビティのインスタンスを持っておこうという時
//メンバ変数
private Activity activity;
//onStart() あたりで
× this.activity = getActivity();
○ this.activity = new WeakReference<Activity>(getActivity()).get();
弱参照とは、参照インスタンスである。
WeakReference クラスのインスタンス。
new WeakReference<型指定>(参照されるインスタンス) というコンストラクタで作成する。
このインスタンス自体は参照であってお目当てのインスタンスではない。
get() メソッドによって参照されているインスタンスを取り出す。
---------------------------------
インナークラスを持つフラグメントの見本
---------------------------------
public class MyFragment extends AbsFragmentWithViewFlipper{
///////////////////////////////////////////////////////////
//フィールド
///////////////////////////////////////////////////////////
//ボタン
private Button btn;
//ボタンのクリックリスナー
private MyOnClickListener listener;
///////////////////////////////////////////////////////////
/**
* ライフサイクル:onStart()
* フラグメントがユーザーに見えるように生成された
* タイミングで呼び出される。
*
* アニメーションの開始など、表示に関わる初期化処理を行う。
*/
@Override
public void onStart(){
super.onStart();
//ボタン
this.btn = (Button)getActivity().findViewById(R.id.btn);
//クリックリスナー作成
this.listener = new MyOnClickListener(this);
//クリックリスナーをセット
this.btn.setOnClickListener(listener);
}//function
///////////////////////////////////////////////////////////
//クラス内クラス
///////////////////////////////////////////////////////////
/**
* スイッチ操作時のリスナー
*/
private static class MyOnClickListener implements OnClickListener{
//外側クラスのインスタンス
private MyFragment parent;
//////////////////////////////
/**
* コンストラクタ
*/
public MyOnClickListener(MyFragment fragment){
//弱参照経由で外側クラスを受け取る
parent = new WeakReference<MyFragment>(fragment).get();
}//function
//////////////////////////////
/**
* クリック時
*/
@Override
public void onClick(
View view
){
//外側クラスにアクセスする時は「parent」を使う
}//function
}//class
}//class
仕事中に気づいたプログラミング上のTipsや備忘録をメモしておくための場所です。
[PHP][Android]など
ブログ主:いしいたける
メインのWebサイト(マンガ) : http://loveandcomic.com/
2015年10月29日木曜日
2014年8月21日木曜日
【Android】JAVAでXMLを使う際の親子関係に注意
WebAPIなどから取得したXMLを解析したいことがよくある。
<key>value</key>
この「key」と「value」とは同じ世代のように見える。
node.getNodeName(); →「key」が取得できる時
node.getNodeValue(); →「value」が取得できそうに見える
しかしそうではない。
<親>子</親>
なんとこいつらの間にも階層がある。
node.getNodeName();
→「key」が取得できる時、
node.getFirstChild().getNodeValue();
→「value」を取得するならもうひと段階子孫に行かねばならない。
【Android】インナークラスから外側のクラスにアクセスする
インナークラスにおいて、「外側のクラス名.this」と書けば良い。
参考:
http://www.ne.jp/asahi/hishidama/home/tech/java/class_use.html
こんな感じ:
********************************************************
参考:
http://www.ne.jp/asahi/hishidama/home/tech/java/class_use.html
こんな感じ:
********************************************************
public class OuterClass{
public void testMethod(){
System.out.println("OuterClassのtestMethod()です。");
}//function
//////////////////////////////////
/**
* インナークラス
*/
public class InnerClass{
public void testMethodInner(){
//ここで外側のクラスを主語にしたい時、 //「外側のクラス名.this」とする。
OuterClass.this.testMethod();
}//function
}//class
}//class
********************************************************
登録:
投稿 (Atom)