SQLの窓

2017年10月26日


別に納品するわけでは無いので、Android の ListView のカスタマイズなんてこれで十分でしょ / TestArrayAdapter バージョン2

前のバージョンはこちらになりますが、世の中に腐るほどある getView 内の記述を外に出しただけのものでした。しかし、よくよく考えてみると、Adapter 内で セットされているデータを取り出して、そのクラスで引数に渡したらもっと楽だし、View のセットなんかも、Adapter 内ですればいい事に気が付きました。

これで、いろんなテストを気楽に出来る人が増えると思うわけです。

TestArrayAdapter
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;

public class TestArrayAdapter<T> extends ArrayAdapter<T> {

	public interface OnGetViewListener<T> {
		abstract public void onGetViewListener(int position, View convertView, ViewGroup parent, T item);
	}

	private OnGetViewListener listener = null;
	private int resource;
	private LayoutInflater inflater;

	public TestArrayAdapter(Context context, int resource, OnGetViewListener listener) {
		super(context, resource);
		this.listener = listener;
		this.resource = resource;
		this.inflater = (LayoutInflater)context.getSystemService
				(Context.LAYOUT_INFLATER_SERVICE);
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		if ( listener != null ) {

			if (convertView == null) {
				convertView = inflater.inflate(resource, null);
			}

			T item = this.getItem(position);

			listener.onGetViewListener(position, convertView, parent, item);
			return convertView;
		}
		return super.getView(position, convertView, parent);
	}
}

呼び出し側は、正式には以下のようにインターフェイスにも<WebData> を指定する事で引数の値を WebData として取得できます。しかし、面倒な場合は <WebData> を指定せずに引数を Object でもらってキャストして使えばいいはずです。
		// *******************************
		// ListView で一覧
		// *******************************
		listView = (ListView) MainControl.this.findViewById(R.id.listView);
		arrayAdapter = new TestArrayAdapter<WebData>(MainControl.this, R.layout.item, new TestArrayAdapter.OnGetViewListener<WebData>() {
			@Override
			public void onGetViewListener(int position, View convertView, ViewGroup parent, WebData item) {

				TextView textView;

				textView = convertView.findViewById(R.id.textCode);
				textView.setText(item.社員コード);

				textView = convertView.findViewById(R.id.textName);
				textView.setText(item.氏名);

				textView = convertView.findViewById(R.id.textType);
				textView.setText(item.所属名);
			}
		});
		listView.setAdapter(arrayAdapter);


画面
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">


    <TextView
        android:id="@+id/textCode"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"/>

    <TextView
        android:id="@+id/textName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black"
        android:textSize="23sp"/>

    <TextView
        android:id="@+id/textType"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="6dp"
        android:textSize="18sp"/>


</LinearLayout>




WebData
public class WebData {

	String 社員コード;
	String 氏名;
	String フリガナ;
	String 所属;
	String 性別;
	int 給与;
	String 手当;
	String 管理者;
	String 生年月日;
	String 生年月日2;
	String 所属名;

	@Override
	public String toString() {
		return 氏名;
	}
}


WebData は 『Java : Class 構造より、update 文を作成する』でも使用しています



タグ:android
posted by lightbox at 2017-10-26 20:00 | 2017 Android Studio | このブログの読者になる | 更新情報をチェックする

2017年10月21日


Java : Class 構造より、update 文を作成する

作ったのは Android Studio です。

以下のクラスですが、一目して ListView 用のクラスである事が解ると思います( toString が表示用 )。また、JSON を Google Gson でデシリアライズする事を想定しているので、C 言語の構造体のような単純な定義です。

WebData クラス
public class WebData {

	String 社員コード;
	String 氏名;
	String フリガナ;
	String 所属;
	String 性別;
	int 給与;
	String 手当;
	String 管理者;
	String 生年月日;
	String 生年月日2;
	String 所属名;

	@Override
	public String toString() {
		return 氏名;
	}
}


この Class のインスタンスに、画面から入力データをセットし、Class 構造を取得して Update 文の where 以降以外を作成するコードが以下です。

buildUpdate メソッド
	public String buildUpdate(String table, Object obj, Class<?> cls) {
		String result = "";

		Field[] flds = cls.getDeclaredFields();
		String type = "";
		String col = "";
		String val = "";
		for( Field fld : flds ) {

			// null 値の場合無視
			try {
				if ( fld.get( obj ) == null ) continue;
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}

			// フィールド名( 列名に一致させた Class 定義 )
			col = fld.getName();
			try {
				// 値( 文字列 )
				val = fld.get( obj ).toString();

			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}

			// データ型 : この場合、int かそれ以外
			type = fld.getType().getName();

			if (!result.equals("")) {
				result += ",";
			}
			if (type.equals("int")) {
				if ( val.equals("") ) {
					result += String.format(" %s = null ", col);
				}
				else {
					result += String.format(" %s = %s ", col, val);
				}
			}
			else {
				if ( val.equals("") ) {
					result += String.format(" %s = null ", col);
				}
				else {
					result += String.format(" %s = '%s' ", col, val);
				}
			}

		}

		result = String.format("update %s set %s", table, result );

		return result;
	}

※ 本来、StringBuilder 等を使用するところを += 演算子を使用しているのはコードを見やすくする為です

エラー処理は最低限で作られていますが、重要なのは Field オブジェクトなので、ご理解下さい。

冒頭に、cls.getDeclaredFields() で、定義されている Field オブジェクトの配列を取得して、ループ処理しているだけです。

引数より、Object として、WebData のインスタンスが渡されて、fld.get( obj ).toString() でデータを取得し、fld.getName() として取得された文字列は列名と一致する事を想定しています。

あとは、fld.getType().getName() で、int かそれ以外でシングルクォートの使い方を決めるわけです。

以下は、その呼び出しコードです。
		WebData curInput = new WebData();

		String code = helper.getTextViewString(R.id.textViewCode);

		// 使用しないフィールドには null をセットする
		curInput.社員コード = null;
		curInput.所属名 = null;
		curInput.生年月日2 = null;

		curInput.氏名 = helper.getEditTextString(R.id.editText1);
		curInput.フリガナ = helper.getEditTextString(R.id.editText2);
		curInput.所属 = helper.getEditTextString(R.id.editText3);
		curInput.給与 = Integer.parseInt(helper.getEditTextString(R.id.editText5));
		curInput.手当 = helper.getEditTextString(R.id.editText6);
		curInput.管理者 = helper.getEditTextString(R.id.editText7);
		curInput.生年月日 = helper.getEditTextString(R.id.editTexBirth);

		curInput.性別 = ((Spinner)(helper.mainActivity).findViewById(R.id.spinner)).getSelectedItemPosition()+"";

		String update = helper.buildUpdate("社員マスタ", curInput, WebData.class );
		String text = update + String.format(" where 社員コード = '%s' ", code );



null を設定して、除外するフィールドを決めています。なので、このコードでは意図的に空文字を文字列の列にセットする事ができません。そういう場合は、仕様を追加します。



タグ:java Reflect
posted by lightbox at 2017-10-21 01:15 | 2017 Android Studio | このブログの読者になる | 更新情報をチェックする

2017年09月23日


ViewSwitcher を使用した2画面アプリ (5) : SQLiteデータを更新する

この内容は、ViewSwitcher を使用した2画面アプリ (4) : SQLiteデータをインポートしてリストビューに表示するより続いています。
更新部分に特化したコードにする為に、MainControl をさらに継承して、マニフェストの初期画面を新しいクラス( MainUpdate ) に変更します。 特別な部分は特に無く、更新ボタンをクリックすると更新するだけです。但し、新規と修正の二通りがあるので、textViewCode の表示状態を取得して、どちらを実行するか決定しています。
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;

public class MainUpdate extends MainControl {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				Log.i("lightbox","タップされました");

				String scode = arrayList.get(position);
				helper.getTextView(R.id.textViewCode).setText(scode);

				// キーを渡して SQLite にアクセスする
				loadData(scode);

				// 画面を切り替える
				helper.showEditView();

			}
		});

		// 更新ボタンの処理
		MainUpdate.this.findViewById(R.id.buttonUpdate).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				Log.i("lightbox","更新ボタンがクリックされました");

				//alertDialog.show();
				helper.showDialog("更新してよろしいですか?", new Helper.OnDialogOkListener() {

					@Override
					public void onDialogOkListener() {
						Log.i("lightbox","ダイアログで、OK ボタンがクリックされました");

						if (  helper.getTextView(R.id.textViewCode).getVisibility() == View.VISIBLE  ) {
							updateData();
						}
						else {
							insertData();
						}

					}

				});

			}
		});
	}

	// *******************************
	// データの更新
	// *******************************
	private void updateData() {

		Log.i("lightbox","updateData");

		String scode = helper.getTextViewString(R.id.textViewCode);
		String sname = helper.getEditTextString(R.id.editText1);
		String furi = helper.getEditTextString(R.id.editText2);

		values.clear();
		values.put("sname", sname);
		values.put("furi", furi);
		db.update("syain", values, String.format("scode='%s'", scode), null);

		loadView();
		helper.showFirstView();
	}

	// *******************************
	// データの登録
	// *******************************
	private void insertData() {

		Log.i("lightbox","insertData");

		String scode = helper.getTextViewString(R.id.editTextCode);
		String sname = helper.getTextViewString(R.id.editText1);
		String furi = helper.getTextViewString(R.id.editText2);

		values.clear();
		values.put("scode", scode);
		values.put("sname", sname);
		values.put("furi", furi);
		db.insert("syain", null, values);

		loadView();
		helper.showFirstView();

	}

	// *******************************
	// 編集用データの表示
	// *******************************
	private void loadData(String scode) {

		String sql = String.format("select * from %s where scode='%s' ", "syain", scode);
		Cursor cursor = mySQLite.getReadableDatabase().rawQuery(sql, null);
		Boolean isData = null;
		isData = cursor.moveToFirst();

		String sname = cursor.getString(cursor.getColumnIndex("sname"));
		helper.setEditTextString(R.id.editText1,sname);
		String furi = cursor.getString(cursor.getColumnIndex("furi"));
		helper.setEditTextString(R.id.editText2,furi);

		cursor.close();

	}

}




posted by lightbox at 2017-09-23 17:38 | 2017 Android Studio | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり

フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり