Dagger2(android support module)をつかってFragmentにDIする
Dagger2(android support module)をつかってFragmentにDIする方法をまとめていく。
HasSupportFragmentInjectorを実装する
MainActivityにHasSupportFragmentInjectorを継承させ必要な実装をします。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class MainActivity : AppCompatActivity(), HasSupportFragmentInjector {
@Inject
lateinit var androidInjector: DispatchingAndroidInjector<Fragment>
override fun supportFragmentInjector() = androidInjector
override fun onCreate(savedInstanceState: Bundle?) {
AndroidInjection.inject(this)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setContentFragment(R.id.mainLayout)
}
private fun setContentFragment(containerViewId: Int) {
supportFragmentManager.let { manager ->
manager.findFragmentById(containerViewId)?.let { return }
ForecastsFragment.newInstance().apply {
manager?.beginTransaction()?.add(containerViewId, this)?.commit()
}
}
}
}
|
Fragmenのモジュールをまとめる
Fragmentで管理するモジュールを MainModule
としてまとめる。
1
2
3
4
5
6
7
|
@Module
internal abstract class MainModule {
@ContributesAndroidInjector
abstract fun contributeMainFragment(): ForecastsFragment
}
|
MainActivityのSubcomponentにMainModuleを追加する。
1
2
3
4
5
6
|
@Module
internal abstract class UiModule {
@ContributesAndroidInjector(modules = [MainModule::class])
internal abstract fun contributeMainActivity(): MainActivity
}
|
今後、MainActivityに機能が追加する場合は、MainModuleに依存するモジュールを追加していく。
Fragmenのライフサイクルに合わせてInject
サンプルのコードではonAttach
でInjetctをしている。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
class ForecastsFragment : Fragment() {
@Inject
lateinit var openWeatherMapRepository: OpenWeatherMapRepository
private var listView: ListView by Delegates.notNull()
override fun onAttach(context: Context?) {
AndroidSupportInjection.inject(this)
super.onAttach(context)
}
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater?.inflate(R.layout.forcasts_fragment, container, false) ?: return null
listView = view.findViewById<ListView>(R.id.list_view)
return view
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
openWeatherMapRepository.findForecastByDaily()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { forecasts ->
listView.adapter = ArrayAdapter<String>(activity, android.R.layout.simple_list_item_1,
forecasts.list.map {
"%s - %s %s/%s".format(
DateUtils.formatDateTime(activity, it.dt * 1000L, FORMAT_NO_YEAR),
it.weather.get(0).main, it.temp.min, it.temp.max)
})
}
}
companion object {
fun newInstance() = ForecastsFragment()
}
}
|
- Fragmentの理解は公式のドキュメントが分かりやすい。
- Fragmentを部品と捉えてタブレットとハンドセットで異なるレイアウトでも部品(Fragment)を組み合わせることで柔軟に対応することができるし部品の再利用も容易にできる。
コード
今回のコードはこちらのPRにまとまっていますので参考になれば嬉しいです。