AsyncTaskLoaderの使い方
AsyncTaskが非推奨ということでAsyncTaskLoaderを使ってみたんだけど使いにくいということで解説
今回はネットから何か拾ってくることを想定して書いてみました。
まず起動する側(ActivityやFragmentから)に書かないといけないこと
public class MainActivity extends FragmentActivity implements LoaderManager.LoaderCallbacks<String>, View.OnClickListener { public static String KEY = "key"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Bundle bundle=new Bundle(); bundle.putString(KEY,/* 取得したいページ */); //SupportLibrary使ってない場合はgetLoaderManager().initLoader(0,bundle,this); getSupportLoaderManager().initLoader(0,bundle,this); } @Override public Loader<String> onCreateLoader(int id, Bundle args) { Log.d("onCreateLoader","onCreateLoader"); URL url = null; try { url=new URL(/* urlの内容 */); } catch (MalformedURLException e) { e.printStackTrace(); return null; } MyAsyncTaskLoader loader= new MyAsyncTaskLoader(this,url); //loader.startLoading(); return loader; } @Override public void onLoadFinished(Loader<String> loader, String data) { Log.d("onLoadFinished",data); //ここでdataをつかう } @Override public void onLoaderReset(Loader<String> loader) { } }
AsyncTaskLoaderの起動は
getLoaderManager().initLoader(0,bundle,this);
で行って
onCreateLoader
でLoaderの作成して返してLoaderが動き出す。結果を
onLoadFinished
で受け取るのが基本的な構造
AsyncTaskLoader側は
public class MyAsyncTaskLoader extends android.support.v4.content.AsyncTaskLoader<String> { URL mUrl; String mHtml; public MyAsyncTaskLoader(Context context, URL url) { super(context); mUrl = url; } @Override protected void onStartLoading() { if (mHtml != null) { //利用可能な場合は、すぐに結果を返す。 deliverResult(mHtml); } if (takeContentChanged() || mHtml == null) { forceLoad(); } } @Override protected void onStopLoading() { cancelLoad(); } @Override public void deliverResult(String data) { if (isReset()) { if (mHtml != null) { // ローダが停止している間の非同期クエリが入って来ました。我々は結果を必要としません。 onReleaseResources(mHtml); } } String oldHtml = mHtml; mHtml = data; if (isStarted()) { // ローダーが現在起動している場合、我々はすぐにその結果を提供することができます。 super.deliverResult(data); } if (oldHtml != null) { onReleaseResources(oldHtml); } } @Override public void onCanceled(String data) { super.onCanceled(data); // この時点では、必要に応じて「アプリ」に関連したリソースを解放することができます。 onReleaseResources(data); } @Override protected void onReset() { super.onReset(); // ローダが停止されていることを確認します。 onStopLoading(); // この時点では、必要に応じて「アプリ」に関連したリソースを解放することができます。 if (mHtml != null) { onReleaseResources(mHtml); mHtml = null; } } @Override public String loadInBackground() { StringBuilder stringBuffer = new StringBuilder(); try { HttpURLConnection httpURLConnection = (HttpURLConnection) mUrl.openConnection(); httpURLConnection.setConnectTimeout(10 * 1000); httpURLConnection.setReadTimeout(30 * 1000); httpURLConnection.setRequestMethod("GET"); try { BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream())); String line; while ((line = bufferedReader.readLine()) != null) { stringBuffer.append(line).append("\n"); } bufferedReader.close(); } catch (Exception e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } mHtml = stringBuffer.toString(); return mHtml; } /** * Helper function to take care of releasing resources associated * with an actively loaded data set. */ protected void onReleaseResources(String apps) { // For a simple List<> there is nothing to do. For something // like a Cursor, we would close it here. } }
onStartLoading
が最初に実行されてその中の
forceLoad()
が実行されると
loadInBackground()
の中が実行される
このloadInBackground()の中に大体やりたい事(今回はネットから拾ってくる)をする
loadInBackground()の返り値が
deliverResult()
を通ってActivityまたはFragment側のonLoadFinishedに渡る