はじめに (対象読者・この記事でわかること)
この記事は、Androidアプリ開発にJavaを使っている中級者〜上級者の方を対象にしています。特に「ActivityとAdapterの責任がごちゃごちゃしていてテストが書きづらい」「画面回転で落ちる」「ListViewの更新処理がActivityにベタ書きで汚い」と感じている方に最適です。
読み進めることで、以下のことがわかります。 - ActivityがAdapterの内部実装を知らなくてもよい設計の作り方 - インターフェースを使った疎結合なコールバックの実装 - 依存性注入(DI)なしでも単体テスト可能なAdapterの書き方 - 画面回転でもデータが破棄されない対策
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。 - Javaの基本的な文法(匿名クラス、インターフェース) - Android基礎(Activity/Fragmentのライフサイクル) - ListViewとArrayAdapterの基礎的な使い方
なぜActivityとArrayAdapterを疎結合にする必要があるのか
Android開発を始めた頃、「とりあえず動けばOK」とActivityに直接ListViewの参照を持たせ、AdapterをnewしてsetAdapterするコードを書いたことはないでしょうか?
Java// 典型的な密結合コード public class MainActivity extends AppCompatActivity { private List<Book> books = new ArrayList<>(); private ArrayAdapter<Book> adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView listView = findViewById(R.id.list); adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, books); listView.setAdapter(adapter); listView.setOnItemClickListener((parent, view, position, id) -> { Book b = books.get(position); Toast.makeText(this, b.title, Toast.LENGTH_SHORT).show(); }); } }
このままだと以下の問題が起きます。 1. テストが書きづらい:Activityをインスタンス化しないとAdapterの振る舞いを検証できない 2. 画面回転でデータ消失:Activityが再生成されるたびにbooksリストがリセットされる 3. 責務の重複:クリック処理もActivityが持っているため、Adapterの再利用が不可能 4. 並列開発が困難:UI担当とデータ担当が同じファイルを触ることになりコンフリクトしやすい
疎結合にすることで、これらの問題を解決し、保守性・拡張性・テスタビリティを同時に高められます。
ステップバイステップで実装する疎結合Adapter
ステップ1:コールバック用インターフ
