プロジェクトの作成

1.新規プロジェクトとしてEJAppを作成する。

Assetsフォルダの作成

2.新しいプロジェクトを作成したらまずassetsフォルダを作ろう。
appをオプションクリックしてNew->Folder->AssetsFolderを選択する。

3.Assetsフォルダはsrc/main/の直下に配置されなければならない。そこに置くか?というダイアログがでるのでチェックしてfinish

4.フォルダが配置されたことを確認

5.今回はtsvファイルを元にデータベースを作成する。以下のファイルをダウンロードしAssetsフォルダに配置する。
(ファイル名をejdic-hand-utf8.tsvとすること)

レイアウトの作成

6.activity_main.xmlを以下のように編集する。

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.mjpurin.ejapp.MainActivity">

    <ProgressBar
        android:id="@+id/pb"
        style="@android:style/Widget.DeviceDefault.Light.ProgressBar"
        android:layout_width="0dp"
        android:layout_height="16dp"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/et"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:ems="10"
        android:hint="@android:string/search_go"
        android:inputType="textPersonName"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/pb" />

    <Spinner
        android:id="@+id/sp"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toRightOf="@+id/et"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toBottomOf="@+id/pb"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp" />

    <Button
        android:id="@+id/button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:onClick="btClick"
        android:text="検索"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et" />

    <ListView
        android:id="@+id/lv"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="8dp"
        android:layout_marginRight="8dp"
        android:layout_marginTop="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button" />
</android.support.constraint.ConstraintLayout>

7.以下のようになればOKだ。

クラスの作成

8.Word.javaを以下のように作成する。(パッケージを環境に合わせて付与すること)

package com.example.xxxxxx;
import java.io.Serializable;

public class Word implements Serializable{
    public int id;
    public String title;
    public String body;

    @Override
    public String toString() {
        String summary;
        if(this.body.length() > 14){
            summary=this.body.substring(0,14)+"...";
        }else{
            summary=this.body;
        }
        return String.format("%s  %s",this.title,summary);
    }
}

DAOの作成

9.WordDAO.javaを以下のように作成

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteStatement;

import java.util.List;


public class WordDAO {
    private SQLiteDatabase db;
    public void setDb(SQLiteDatabase db){
        this.db=db;
    }
    public void createTable(){
        String sql="CREATE TABLE words("+
                "id INTEGER PRIMARY KEY AUTOINCREMENT,"+
                "title TEXT,"+
                "body TEXT)";
        this.db.execSQL(sql);
    }
    public void createData(List<Word> list){
        String sql="INSERT INTO words(title,body) VALUES(?,?)";
        SQLiteStatement stt=this.db.compileStatement(sql);
        this.db.beginTransaction();
        try{
            for(Word word:list){
                stt.bindString(1,word.title);
                stt.bindString(2,word.body);
                stt.executeInsert();
            }
            this.db.setTransactionSuccessful();
        }catch(SQLiteException e){
            e.printStackTrace();
        }finally {
            this.db.endTransaction();
        }

    }
    public void findAll(String searchWord,List<Word> list){
        list.clear();
        String sql="SELECT * FROM words WHERE title LIKE ?";
        String[] param={searchWord};
        Cursor cursor=this.db.rawQuery(sql,param);
        while(cursor.moveToNext()){
            Word word=new Word();
            word.id=cursor.getInt(cursor.getColumnIndex("id"));
            word.title=cursor.getString(cursor.getColumnIndex("title"));
            word.body=cursor.getString(cursor.getColumnIndex("body"));
            list.add(word);
        }

    }
    public void dropTable(){
        String sql="DROP TABLE IF EXISTS words";
        this.db.execSQL(sql);
    }

}

SQLiteOpenHelperの作成

10.SQLiteOpenHelperクラスを継承したOpenHelper.javaを以下のように作成する。


import android.content.Context;
import android.content.res.AssetManager;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

public class OpenHelper  extends SQLiteOpenHelper{
    private Context context;
    private WordDAO dao;
    private String tsv= "ejdic-hand-utf8.tsv";
    public OpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        this.context=context;
        dao=new WordDAO();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        dao.setDb(db);
        dao.createTable();
        dao.createData(getListFromTSV(tsv));
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        dao.setDb(db);
        dao.dropTable();
        this.onCreate(db);
    }
    private List<Word> getListFromTSV(String tsv){
        List<Word> list=new ArrayList<>();
        AssetManager am=context.getAssets();

        try {
            InputStream is=am.open(tsv);
            InputStreamReader isr=new InputStreamReader(is);
            BufferedReader br=new BufferedReader(isr);
            String line;
            while((line=br.readLine()) != null){
                Word word=new Word();
                String[] vals=line.split("\t");
                word.title=vals[0];
                word.body=vals[1];
                list.add(word);

            }
            br.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

}

詳細表示ようダイアログの作成

11.ResultDialog.javaを以下のように作成する。

import android.app.Dialog;
import android.app.DialogFragment;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;

public class ResultDialog extends DialogFragment {
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        final Word item=(Word)getArguments().getSerializable("word");

        AlertDialog.Builder builder=new AlertDialog.Builder(getActivity());
        builder.setTitle(item.title);
        builder.setMessage(item.body);
        builder.setPositiveButton("close", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {

            }
        });

        return builder.create();
    }
}

MainActivityの作成

12.MainActivity.javaを以下のように編集する。


import android.app.DialogFragment;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Spinner;

import java.util.ArrayList;
import java.util.List;


public class MainActivity extends AppCompatActivity {
    public ProgressBar pb;
    private EditText et;
    private Spinner sp;
    private ListView lv;
    private Button bt;
    private WordDAO dao;
    private List<Word> list=new ArrayList<>();
    private ArrayAdapter<Word> lvAdapter;
    private Handler handler=new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pb=(ProgressBar)findViewById(R.id.pb);
        et=(EditText)findViewById(R.id.et);
        et.setVisibility(View.GONE);
        sp=(Spinner)findViewById(R.id.sp);
        sp.setVisibility(View.GONE);
        bt=(Button)findViewById(R.id.button);
        bt.setVisibility(View.GONE);
        lv=(ListView)findViewById(R.id.lv);
        //DB登録作業は時間がかかるので裏で処理する。
        new Thread(new Runnable() {
            @Override
            public void run() {
                //初回のみここでDBを生成するので時間がかかる
                OpenHelper helper=new OpenHelper(getApplicationContext(),"ejword.db",null,1);
    
                SQLiteDatabase db=helper.getWritableDatabase();
                dao=new WordDAO();
                dao.setDb(db);
                //処理完了したらhandlerにビューの更新処理をキューイングする。
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        pb.setVisibility(View.GONE);
                        et.setVisibility(View.VISIBLE);
                        sp.setVisibility(View.VISIBLE);
                        bt.setVisibility(View.VISIBLE);
                    }
                });

            }
        }).start();

        //spinner生成
        String[] items={"前方一致","一致","後方一致"};
        ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_spinner_item, items);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        sp.setAdapter(adapter);
        //lv生成
        lvAdapter=new ArrayAdapter<>(this,android.R.layout.simple_list_item_1,this.list);
        lv.setAdapter(lvAdapter);
        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Word word=list.get(position);
                Bundle bundle=new Bundle();
                bundle.putSerializable("word",word);
                DialogFragment dialog=new ResultDialog();
                dialog.setArguments(bundle);
                dialog.show(getFragmentManager(),"TAG");
            }
        });
    }
    public void btClick(View v){
        String mode=sp.getSelectedItem().toString();
        String searchWord=et.getText().toString();
        if(mode.equals("前方一致")){
            searchWord=searchWord+"%";
        }else if(mode.equals("後方一致")){
            searchWord="%"+searchWord;
        }
        dao.findAll(searchWord,this.list);
        lvAdapter.notifyDataSetChanged();
    }
}

実行

13.実行してみよう。最初に見た動画のように動けば成功だ。