ContentProviderを使ったTodoリストアプリを作る
最終更新日:2015-07-07
Todoを扱うContentProviderの実装ができたので、早速これを使ったアプリを作ってみます。
ここまでの実装はここにあります。
アプリは、ログイン画面とリスト画面の2画面で構成します。ログイン画面はおまけみたいな感じではありますが。。。
まずはログイン画面。単にユーザーIDを入力してもらうだけにしています。ボタンをタップしたときの処理だけ紹介します。
public class LoginFragment extends Fragment {
@Bind(android.R.id.edit)
EditText mUsernameEdit;
// 中略
@OnClick(android.R.id.button1)
void loginClicked() {
String username = mUsernameEdit.getText().toString();
if (TextUtils.isEmpty(username)) { return; }
FragmentManager manager = getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.replace(R.id.container, TodoListFragment.newInstance(username));
transaction.commit();
}
}
入力されたユーザー名を次のFragmentに渡しているだけですね。
次にメインとなるリスト画面。やや長いですがぜんぶ載せます。
public class TodoListFragment extends ListFragment {
private static final String ARGS_USERNAME = "username";
private static final int ID_LOADER = 1;
// argument
private String mUsername;
@Bind(android.R.id.edit)
EditText mEdit;
public static TodoListFragment newInstance(String username) {
TodoListFragment fragment = new TodoListFragment();
Bundle args = new Bundle();
args.putString(ARGS_USERNAME, username);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
mUsername = args.getString(ARGS_USERNAME);
}
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_list, container, false);
ButterKnife.bind(this, root);
// init adapter
CursorAdapter adapter = new SimpleCursorAdapter(getActivity(), R.layout.item_todo, null,
new String[]{TodoColumns.TODO}, new int[]{android.R.id.text1}, 0);
setListAdapter(adapter);
return root;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
loadTodo();
}
@Override
public void onDestroyView() {
super.onDestroyView();
ButterKnife.unbind(this);
}
private void loadTodo() {
LoaderManager manager = getLoaderManager();
manager.initLoader(ID_LOADER, null, mCallback);
}
private LoaderManager.LoaderCallbacks<Cursor> mCallback = new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), Uri.parse("content://com.mokelab.todo.provider/users/" + mUsername + "/todos"),
null, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
CursorAdapter adapter = (CursorAdapter) getListAdapter();
adapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
CursorAdapter adapter = (CursorAdapter) getListAdapter();
adapter.swapCursor(null);
}
};
@OnClick(android.R.id.button1)
void addClicked() {
String todo = mEdit.getText().toString();
if (TextUtils.isEmpty(todo)) {
return;
}
ContentValues values = new ContentValues();
values.put(TodoColumns.TODO, todo);
getActivity().getContentResolver().insert(
Uri.parse("content://com.mokelab.todo.provider/users/" + mUsername + "/todos"),
values);
mEdit.setText("");
}
}
順に見ていきましょう。
まず、onCreate()で、引数として渡されたユーザーIDを取り出します。
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Bundle args = getArguments();
mUsername = args.getString(ARGS_USERNAME);
}
次に、onCreateView()でCursorAdapterをListAdapterとしてセットします。この時点でCursorは取得できていないので、第3引数にはnullをセットしておきます。
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_list, container, false);
ButterKnife.bind(this, root);
// init adapter
CursorAdapter adapter = new SimpleCursorAdapter(getActivity(), R.layout.item_todo, null,
new String[]{TodoColumns.TODO}, new int[]{android.R.id.text1}, 0);
setListAdapter(adapter);
return root;
}
onActivityCreated()で、Loaderの初期化を行います。
private void loadTodo() {
LoaderManager manager = getLoaderManager();
manager.initLoader(ID_LOADER, null, mCallback);
}
LoaderCallbacksでは、CursorLoaderを生成します。CursorLoaderはContentProviderからデータを読み込むのに便利なLoaderです。データの取得が終わったら、CursorAdapterのswapCursor()で取得したCursorオブジェクトをセットします。これだけでTodoの読み込み部分は完了です。
private LoaderManager.LoaderCallbacks<Cursor> mCallback = new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
return new CursorLoader(getActivity(), Uri.parse("content://com.mokelab.todo.provider/users/" + mUsername + "/todos"),
null, null, null, null);
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
CursorAdapter adapter = (CursorAdapter) getListAdapter();
adapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
CursorAdapter adapter = (CursorAdapter) getListAdapter();
adapter.swapCursor(null);
}
};
最後に、データを追加する部分です。ContentResolverのinsert()を呼ぶだけなのでこちらも簡単ですね。
@OnClick(android.R.id.button1)
void addClicked() {
String todo = mEdit.getText().toString();
if (TextUtils.isEmpty(todo)) {
return;
}
ContentValues values = new ContentValues();
values.put(TodoColumns.TODO, todo);
getActivity().getContentResolver().insert(
Uri.parse("content://com.mokelab.todo.provider/users/" + mUsername + "/todos"),
values);
mEdit.setText("");
}
ContentProviderにinsert()でデータを追加すると、更新通知を実装するで実装した機能により、自動で再取得とリストの更新が行われます。