Android ActivityでDBを頻繁に使うプログラムを開発する場合に、
前項のようなコードをActivity内に組込むのはやめたい。
クラス化にあたっての課題は、処理の結果を呼び出したクラスに渡すか?
非同期処理処理を踏まえてどうするか。。。
で、先人の知恵を借りてListenerを使って呼び出し側で非同期処理の終了を
解るようにして、一件落着
ますます、便利になった。
Peace!!
ソースの先頭には、使い方を書いた。
サーバーサイドのDBプログラムは別途必要です。
ソースコード、どーんと(笑)
/***********************************************************
* AsyncTask<型1, 型2,型3>
* 型1 … Activityからスレッド処理へ渡したい変数の型
* ※ Activityから呼び出すexecute()の引数の型
* ※ doInBackground()の引数の型
* 型2 … 進捗度合を表示する時に利用したい型
* ※ onProgressUpdate()の引数の型
* 型3 … バックグラウンド処理完了時に受け取る型
* ※ doInBackground()の戻り値の型
* ※ onPostExecute()の引数の型
* ※ それぞれ不要な場合は、Voidを設定すれば良い
* --------------------------------------------------------------
* 呼び出す側に以下を追加する
********************************************************************************
* 汎用DBアクセスクラス SqlOpeAsyncTask を使う場合のListener設定
* クラスを使う側で設定する。
* onDestroyは、使うクラス側で重ならなければ使えるかも。未確認
* @return
* /
private SqlOpeAsyncTask.Listener createListener(){
return new SqlOpeAsyncTask.Listener(){
@Override
public void onSuccess(String ret){
// 以下は個々のプログラム毎に記述
etKata.setText(ret);
}
};
}
@Override
protected void onDestroy() {
SqlOpeAsyncTask.setListener(null);
super.onDestroy();
}
// 呼び出し例
String in1 = getResources().getString(R.string.url_srv_gets1);
String in2 = "?100:select kata,tana,hinc,kazu from zaiko where hinc = '15916-1' and tana <> 'REFER' order by tana DESC; ";
SqlOpeAsyncTask retAsyn = new SqlOpeAsyncTask();
retAsyn.setListener(createListener());
String inStr = in1 + in2;
Log.d(TAG, "before Async execute");
retAsyn.execute(inStr);
***********************************************************************/
package com.futureagri.app.thn.hd.java;
import android.nfc.Tag;
import android.os.AsyncTask;
import android.util.Log;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/******************************************************************
* 非同期でデータベース処理をするクラス。
******************************************************************/
public class SqlOpeAsyncTask extends AsyncTask<String, Void, String> {
private Listener listener;
private static final String TAG = "SqlOpeAsyncTask";
private String retString = "";
private TextView textView;
/********************************************************************
* メインスレッドとは別のスレッドで実行されます。
* 非同期で処理したい内容を記述します。
* このメソッドだけは必ず実装する必要があります
* @param data
* @return
*/
@Override
//protected String doInBackground(Object[] data) {
public String doInBackground(String... data) {
// target URL
String urlStr = (String)data[0];
Log.d(TAG, "doInBackground: " + "input sql=" + urlStr);
// Variable of set result texts
//StringBuilder result = new StringBuilder();
String result = "";
//http接続を行うHttpURLConnectionオブジェクトを宣言。finallyで確実に解放するためにtry外で宣言。
HttpURLConnection con = null;
//http接続のレスポンスデータとして取得するInputStreamオブジェクトを宣言。同じくtry外で宣言。
InputStream is = null;
int i = 10;
try {
//URLオブジェクトを生成。
URL url = new URL(urlStr);
//URLオブジェクトからHttpURLConnectionオブジェクトを取得。
con = (HttpURLConnection) url.openConnection();
//http接続メソッドを設定。
con.setRequestMethod("GET");
//接続。
con.connect();
final int status = con.getResponseCode();
if (status == HttpURLConnection.HTTP_OK) {
// Success HTTP GET method
is = con.getInputStream();
result = is2String(is);
is.close();
}else {
Log.d(TAG, "doInBackground: HTTP response error");
}
} catch (MalformedURLException ex) {
ex.printStackTrace();
//} catch (ProtocolException ex) {
//ex.printStackTrace();
Log.d(TAG, "doInBackground: HTTP MalformedURLException");
} catch (IOException ex) {
ex.printStackTrace();
Log.d(TAG, "doInBackground: HTTP IOException");
} finally {
// HttpURLConnectionオブジェクトがnullでないなら解放。
if (con != null) {
con.disconnect();
}
// InputStreamオブジェクトがnullでないなら解放。
if (is != null) {
try {
is.close();
} catch (IOException ex) {
Log.d(TAG,"doInBackground: HTTP close is IOException");
}
}
}
// 非同期で取得したデータをセットする
if ( i == 0) {
Log.d(TAG, "doInBackground: HTTP return : error end");
return "-99999";
}else {
//return result.toString();
retString = result;
return result;
}
}
/*****************************************************************************
* doInBackgroundメソッドの実行後にメインスレッドで実行されます。
* doInBackgroundメソッドの戻り値をこのメソッドの引数として受け取り、
* その結果を画面に反映させることができます
* @param result
*/
@Override
public void onPostExecute(String result) {
//toastMake(result, 0, -200);
Log.d(TAG, "onPostExecute: result :" + result);
String[] ret = result.split("\\|"); // Mac \ -> (option + ¥)
int iMode = Integer.parseInt(ret[0]); // 呼び出した処理番号
int cnt = Integer.parseInt(ret[1]); // 検索数
int retu = Integer.parseInt(ret[2]); // 列数
Log.d(TAG, "onPostExecute: mode:cnt:retu=" + iMode + ":" + cnt + ":" + retu);
//-------------------------------------------------------------
// mode=100 kata,tana,hinc,kazu
//-------------------------------------------------------------
if (iMode == 100) {
retString = iMode + "|" + cnt + "|" + retu + "|";
for (int i = 0; i < cnt * retu; i++) {
retString = retString + ret[3 + i] + "|";
}
}
if (listener != null) {
listener.onSuccess(retString);
}
}
/*****************************************************************************
* InputStreamオブジェクトを文字列に変換するメソッド。変換文字コードはUTF-8。
*
* @param is 変換対象のInputStreamオブジェクト。
* @return 変換された文字列。
* @throws IOException 変換に失敗した時に発生。
*/
private String is2String(InputStream is) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sb = new StringBuffer();
char[] b = new char[2048];
int line;
while(0 <= (line = reader.read(b))) {
sb.append(b, 0, line);
}
return sb.toString();
}
/************************************************************
* Listener 処理を定義する
*
* @param listener
*/
void setListener(Listener listener) {
this.listener = listener;
}
interface Listener {
void onSuccess(String count);
}
}
0 件のコメント:
コメントを投稿