ViewのTagとBeanを使ってあれこれする
TagとOnClickListenerのimplementsで処理の共通化覚書。
ButtonにOnClickLitnerを設定する時に毎回匿名クラスを作成するのは冗長的だし、だからと言ってActivityにimplemetnsしても汎用性が欠ける。
ViewクラスにはTagがあるので、TagにBeanを格納すれば処理の共通化と共通じゃない処理を振り分ける。
例えば、複数のButtonの処理はそれぞれ別だが、共通の処理が多い時とかコピペがいやな時とかは有効。
要するに、独自処理的なものをBeanにして、それをそのまま処理実行するなんかに渡してしまえば解決。
例)
HTML、XML、画像をネットから拾ってくるアプリの場合
詳細な処理は前の記事で書いたので説明はしない
■アプリ概要
- HTML、XML、画像のボタンが有る
- ボタンを押すと、画面遷移する
- 各処理を実行する
この場合、以下の処理が共通になる
- 値をセットする
- コマンド
- URL
- 画面遷移
共通じゃない処理
- 接続先
- 取得対象
- HTML
- XML
- 画像
共通じゃない処理はBeanを使う
Beanには以下の情報がある
- int command : 実行する処理のタイプ
- String url : 接続先
共通じゃない処理をなんかするのは次の画面にまかせる
つまり、次の画面にBeanを渡す
ソース
■TagBean
Serializableを実装させる
package com.example.httpaccess; import java.io.Serializable; public class TagBean implements Serializable{ private static final long serialVersionUID = 1L; private int command; private String url; public TagBean() { } public TagBean(int command, String url) { super(); this.command = command; this.url = url; } public int getCommand() { return command; } public void setCommand(int command) { this.command = command; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } @Override public String toString() { // TODO Auto-generated method stub return "command:" + this.command + " url:" + this.url; } }
■Constant
定数クラス
package com.example.httpaccess; public class Constant { //View#TagのKey public static final int TAG_KEY_URL = 0; public static final int TAG_KEY_COMMAND = 1; public static final String INTENT_KEY_TAGBEAN = "TagBean"; //url用リンク public static final String TARGET_URL_URL = "http://atnd.org/events/1605"; //xml用リンク public static final String TARGET_URL_XML = "http://atnd.org/events.rss"; //binary用リンク public static final String TARGET_URL_BIN = "http://atnd.org/images/event_show_joined.gif"; public static final int COMMAND_URL = 0; public static final int COMMAND_XML = 1; public static final int COMMAND_BIN = 2; public static final int COMMAND_XMLPULL = 3; }
■SampleHttpAccess
BeanとTagを使ってやりたい処理を振り分けてるからOnClickのソースは同じ。
ViewクラスにはmTagというObject型のメンバ変数があって、これに好きなものを入れることができる。
TagにBeanを入れてしまえば独自処理的なものを共通的な扱いができる
あとButtonクラスとかUI関係はみんなViewを継承してるからButton#setTagとかでセットできる。
ViewクラスのmTagを定義してるとこ。
関係ないことだけど、javadocのコメントが参考になる。
/** * The view's tag. * {@hide} * * @see #setTag(Object) * @see #getTag() */ protected Object mTag;
package com.example.httpaccess; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class SampleHttpAccess extends Activity implements OnClickListener{ private Button btURL; private Button btXml; private Button btBin; private Button btXmlPull; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); this.btURL = (Button)findViewById(R.id.ButtonURL); this.btXml = (Button)findViewById(R.id.ButtonXml); this.btBin = (Button)findViewById(R.id.ButtonBin); this.btXmlPull = (Button)findViewById(R.id.ButtonXmpPullparser); this.btURL.setTag(new TagBean(Constant.COMMAND_URL, Constant.TARGET_URL_URL)); this.btXml.setTag(new TagBean(Constant.COMMAND_XML, Constant.TARGET_URL_XML)); this.btBin.setTag(new TagBean(Constant.COMMAND_BIN, Constant.TARGET_URL_BIN)); this.btXmlPull.setTag(new TagBean(Constant.COMMAND_XMLPULL, Constant.TARGET_URL_XML)); this.btURL.setOnClickListener(this); this.btXml.setOnClickListener(this); this.btBin.setOnClickListener(this); this.btXmlPull.setOnClickListener(this); } @Override public void onClick(View arg0) { Intent i = new Intent(SampleHttpAccess.this, SampleHttpAccessNext.class); TagBean bean = (TagBean)arg0.getTag(); Log.v("bean", bean.toString()); i.putExtra(Constant.INTENT_KEY_TAGBEAN, (TagBean)arg0.getTag()); startActivity(i); } }
■SampleHttpAccessNext
それぞれの処理実行するやつ。
package com.example.httpaccess; import java.util.ArrayList; import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.widget.ImageView; import android.widget.TextView; import com.example.httpaccess.util.Utils; public class SampleHttpAccessNext extends Activity { private static final String TAG_NAME_TITLE = "title"; private TextView textUrl; private TextView textResult; private TextView textTime; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.next); this.textUrl = (TextView) findViewById(R.id.TextViewUrl); this.textResult = (TextView) findViewById(R.id.TextViewResult); this.textTime = (TextView) findViewById(R.id.TextViewTime); Intent i = getIntent(); TagBean bean = (TagBean) i .getSerializableExtra(Constant.INTENT_KEY_TAGBEAN); String url = bean.getUrl(); int command = bean.getCommand(); this.textUrl.setText(url); StringBuilder sbTime = new StringBuilder(); Long start = System.nanoTime(); sbTime.append("計測開始"); sbTime.append(Utils.BR); switch (command) { case Constant.COMMAND_URL: this.textResult.setText(getHtml(url)); break; case Constant.COMMAND_XML: String[] targets = { TAG_NAME_TITLE, "dummy1", "dummy2" }; this.textResult.setText(getXml(url, targets)); break; case Constant.COMMAND_BIN: Bitmap bmp1 = getImage(url); ImageView image1 = (ImageView) findViewById(R.id.ImageView01); image1.setImageBitmap(bmp1); break; case Constant.COMMAND_XMLPULL: String[] targets2 = { TAG_NAME_TITLE, "dummy1", "dummy2" }; this.textResult.setText(getXmlPull(url, targets2)); break; } Long end = System.nanoTime(); sbTime.append("計測完了 : " + (end - start) + "ナノ秒"); this.textTime.setText(sbTime.toString()); } private String getXml(String url, String[] targetTag) { ArrayList<String> list = Utils.getXmlTags(url, targetTag); StringBuilder sb = new StringBuilder(); for (String val : list) { sb.append(val + "\n"); } return sb.toString(); } private String getHtml(String url) { byte[] byteArray = Utils.getByteArrayFromURL(url); String html = new String(byteArray); return html; } private Bitmap getImage(String url) { byte[] byteArray = Utils.getByteArrayFromURL(url); return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length); } private String getXmlPull(String url, String[] targetTag) { ArrayList<String> list = Utils.getXMLFromURL(url, targetTag); StringBuilder sb = new StringBuilder(); for (String val : list) { sb.append(val + "\n"); } return sb.toString(); } }||< <span style="font-weight:bold;">■Utils</span> HTTP通信してくれるやつとか、XMLパースとか >|java| package com.example.httpaccess.util; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import android.util.Log; import android.util.Xml; public class Utils { public final static String BR = System.getProperty("line.separator"); public static byte[] getByteArrayFromURL(String strUrl) { byte[] byteArray = new byte[1024]; byte[] result = null; HttpURLConnection con = null; InputStream in = null; ByteArrayOutputStream out = null; int size = 0; try { // HTTP接続のオープン URL url = new URL(strUrl); con = (HttpURLConnection) url.openConnection(); con.setRequestMethod("GET"); con.connect(); in = con.getInputStream(); // バイト配列の読み込み out = new ByteArrayOutputStream(); while (true) { size = in.read(byteArray); if (size <= 0) { break; } out.write(byteArray, 0, size); } result = out.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (con != null) con.disconnect(); if (in != null) in.close(); if (out != null) out.close(); } catch (Exception e) { e.printStackTrace(); } } return result; } public static ArrayList<String> getXmlTags(String url, String[] targetTags) { byte[] byteArray = Utils.getByteArrayFromURL(url); ArrayList<String> result = new ArrayList<String>(); if (byteArray == null) { Log.i("getXmlTags", "URLの取得に失敗"); return result; } String data = new String(byteArray); try { final XmlPullParser xpp = Xml.newPullParser(); xpp.setInput(new StringReader(data)); while (true) { int e = xpp.getEventType(); // EventがEND_DOCUMENTなら終了 if (e == XmlPullParser.END_DOCUMENT) { break; } e = xpp.next(); switch (e) { case XmlPullParser.START_TAG: String tag = xpp.getName(); for (String target : targetTags) { if (target.equals(tag)) { result.add(xpp.nextText()); break; } } break; } } } catch (Exception e) { e.printStackTrace(); } return result; } public static ArrayList<String> getXMLFromURL(String url, String[] targetTags) { ArrayList<String> result = new ArrayList<String>(); XmlPullParser xpp = null; try { URL rssurl = new URL(url); XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); xpp = factory.newPullParser(); InputStream is = rssurl.openStream(); xpp.setInput(is, "UTF-8"); while (true) { int e = xpp.getEventType(); if (e == XmlPullParser.END_DOCUMENT) { break; } else { e = xpp.nextToken(); String tag; tag = xpp.getName(); switch (e) { case XmlPullParser.START_TAG: for (String target : targetTags) { if (target.equals(tag)) { result.add(xpp.nextText()); break; } } } } } } catch (XmlPullParserException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } catch (IOException e) { // TODO 自動生成された catch ブロック e.printStackTrace(); } return result; } }