Andriod開発テクニック――Fragmentの怠惰なロード


私たちがアプリケーション開発をしている間に、1つのActivityの中でviewpager(または他のコンテナ)と複数のFragmentを組み合わせて使用する可能性がありますが、fragmentごとにデータをロードしたり、ローカルからロードしたり、ネットワークからロードしたりする必要がある場合は、このactivityが建設されたばかりのときに大量のリソースを初期化する必要があります.このような結果は、もちろん満足しません.では、このfragmentに切り替えたときに初期化することはできますか?
答えはFragmentのsetuserVisibleHintという方法にあります.Fragmentのこのメソッドに関するAPIドキュメント(国内ミラーアドレス:http://zdz.la/YrpKlu):
Set a hint to the system about whether this fragment's UI is currently visible to the user. This hint defaults to true and is persistent across fragment instance state save and restore.
An app may set this to false to indicate that the fragment's UI is scrolled out of visibility or is otherwise not directly visible to the user. This may be used by the system to prioritize operations such as fragment lifecycle updates or loader ordering behavior.
ParametersisVisibleToUser true if this fragment's UI is currently visible to the user (default), false if it is not.
この方法は、このFragmentのUIが表示されているかどうかをシステムに伝えるために使用される.したがって、Fragmentを継承して書き換えるだけで、fragmentが表示されたときにデータロード操作、すなわちFragmentの怠惰なロードを実現することができます.
コードは次のとおりです.
/* * Date: 14-7-17 * Project: Access-Control-V2 */
package cn.irains.access_control_v2.common;
import android.support.v4.app.Fragment;

/*
Author: msdx ([email protected]) 
 Time: 14-7-17  5:46
*/

public abstract class LazyFragment extends Fragment 
{   
 protected boolean isVisible;   
  /*  
    Fragment .    
    @param isVisibleToUser     
   */   
   @Override    
   public void setUserVisibleHint(boolean isVisibleToUser) {       
    super.setUserVisibleHint(isVisibleToUser);       
     if(getUserVisibleHint()) {            
     isVisible = true;          
       onVisible();      
         } else {            
         isVisible = false;         
            onInvisible();     
               } 
                  }
    protected void onVisible(){  
          lazyLoad(); 
             }
    protected abstract void lazyLoad();
    protected void onInvisible(){}
    }

LazyFragmentでは、onVisiable、すなわちfragmentが可視に設定されたときに呼び出され、onInvisible、すなわちfragmentが非可視に設定されたときに呼び出される3つの方法を追加しました.また、onVisibleで呼び出されるlazyLoadの抽象的な方法を書きました.なぜgetUserVisibleHintで直接呼び出さないのかと思うかもしれません.
私がこのように書いたのはコードの多重化のためです.fragmentではビュー(onCreateView()メソッド)を作成する必要があるため、AIDLによって呼び出されるリモート・サービスを初期化するなど、非表示の場合に他の少量の初期化操作を行う必要がある場合があります.一方setuUserVisibleHintはonCreateViewの前に呼び出され、ビューが初期化されていないときにlazyLoadで使用すると、空のポインタの異常が発生します.lazyLoadを抽出する方法は、そのサブクラスがこのようにすることができます.
public class OpenResultFragment extends LazyFragment{ 
//  , 。    
private boolean isPrepared;
    @Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
 {        
 Log.d(LOG_TAG, "onCreateView");        
 View view = inflater.inflate(R.layout.fragment_open_result, container, false);  
 //XXX view  isPrepared = true;        
 lazyLoad();        
 return view;   
  }
    @Override    
    protected void lazyLoad() 
    {       
     if(!isPrepared || !isVisible) 
     {            
     return;        
     } 
      //     }
}

上記のクラスでは、初期化が完了したかどうかを示すフラグビットisPreparedを追加しました.次に、上記の例のように、viewを初期化した後、isPreparedをtrueに設定し、lazyLoad()メソッドを呼び出します.一方,lazyLoad()では,isPreparedとisVisibleのどちらかがtrueでなければ下に進めないと判断する.すなわち、初期化が完了し、表示されている場合にのみロードが継続されるため、初期化が完了していない場合に使用される問題が回避される.
ここではfragmentの怠惰なロード実装についてここまで説明しますが、興味があれば、これに基づいてさらに深く探究することができます.例えば、初期化が遅く、表示されたときにリフレッシュする特性を持つFragmentを書くことができます.