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;
	}
}