Skip to content
This repository was archived by the owner on Aug 22, 2024. It is now read-only.

Commit 428be51

Browse files
committed
[ADDED] [#102] Learning resource activity
[ADDED] Learning resource item adapter and view [ADDED] Data binding [ADDED] DI for the learning resource
1 parent 2d2199e commit 428be51

17 files changed

+404
-23
lines changed

.idea/assetWizardSettings.xml

+5-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/build.gradle

+4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ dependencies {
4747
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
4848

4949
// Android Support libs and Google Android libs
50+
implementation "androidx.appcompat:appcompat:$rootProject.supportAppCompatVersion"
5051
implementation "androidx.legacy:legacy-support-v13:$rootProject.supportLibraryVersion"
5152
implementation "com.google.android.material:material:$rootProject.supportLibraryVersion"
5253
implementation "androidx.cardview:cardview:$rootProject.supportLibraryVersion"
@@ -64,8 +65,11 @@ dependencies {
6465
// ========================================================
6566
// 3rd party libraries
6667
// ========================================================
68+
69+
// Leak Canary
6770
debugImplementation "com.squareup.leakcanary:leakcanary-android:$rootProject.leakcanaryLibraryVersion"
6871

72+
// Timber
6973
implementation "com.jakewharton.timber:timber:$rootProject.timberLibraryVersion"
7074

7175
// Crashlytics

app/src/main/AndroidManifest.xml

+20-17
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,40 @@
1212
android:supportsRtl="true"
1313
android:theme="@style/AppTheme"
1414
tools:ignore="AllowBackup,GoogleAppIndexingWarning">
15-
<activity android:name="com.hossainkhan.android.demo.ui.browse.LayoutBrowseActivity">
15+
<activity android:name=".ui.browse.LayoutBrowseActivity">
1616
<intent-filter>
1717
<action android:name="android.intent.action.MAIN" />
1818

1919
<category android:name="android.intent.category.LAUNCHER" />
2020
</intent-filter>
2121
</activity>
2222
<activity
23-
android:name="com.hossainkhan.android.demo.ui.layoutpreview.LayoutPreviewBaseActivity"
24-
android:parentActivityName="com.hossainkhan.android.demo.ui.browse.LayoutBrowseActivity" />
23+
android:name=".ui.layoutpreview.LayoutPreviewBaseActivity"
24+
android:parentActivityName=".ui.browse.LayoutBrowseActivity" />
2525
<activity
26-
android:name="com.hossainkhan.android.demo.ui.layoutpreview.LayoutVisibilityGoneActivity"
27-
android:parentActivityName="com.hossainkhan.android.demo.ui.browse.LayoutBrowseActivity" />
26+
android:name=".ui.layoutpreview.LayoutVisibilityGoneActivity"
27+
android:parentActivityName=".ui.browse.LayoutBrowseActivity" />
2828
<activity
29-
android:name="com.hossainkhan.android.demo.ui.layoutpreview.LayoutChainStyleActivity"
30-
android:parentActivityName="com.hossainkhan.android.demo.ui.browse.LayoutBrowseActivity" />
29+
android:name=".ui.layoutpreview.LayoutChainStyleActivity"
30+
android:parentActivityName=".ui.browse.LayoutBrowseActivity" />
3131
<activity
32-
android:name="com.hossainkhan.android.demo.ui.layoutpreview.LayoutGuidelineBarrierActivity"
33-
android:parentActivityName="com.hossainkhan.android.demo.ui.browse.LayoutBrowseActivity" />
32+
android:name=".ui.layoutpreview.LayoutGuidelineBarrierActivity"
33+
android:parentActivityName=".ui.browse.LayoutBrowseActivity" />
3434
<activity
35-
android:name="com.hossainkhan.android.demo.ui.layoutpreview.LayoutGuidelineGroupActivity"
36-
android:parentActivityName="com.hossainkhan.android.demo.ui.browse.LayoutBrowseActivity" />
35+
android:name=".ui.layoutpreview.LayoutGuidelineGroupActivity"
36+
android:parentActivityName=".ui.browse.LayoutBrowseActivity" />
3737
<activity
38-
android:name="com.hossainkhan.android.demo.ui.layoutpreview.LayoutDimensionMinMaxActivity"
39-
android:parentActivityName="com.hossainkhan.android.demo.ui.browse.LayoutBrowseActivity" />
38+
android:name=".ui.layoutpreview.LayoutDimensionMinMaxActivity"
39+
android:parentActivityName=".ui.browse.LayoutBrowseActivity" />
4040
<activity
41-
android:name="com.hossainkhan.android.demo.ui.functionaldemo.MovieDetailsPreviewActivity"
42-
android:parentActivityName="com.hossainkhan.android.demo.ui.browse.LayoutBrowseActivity" />
41+
android:name=".ui.functionaldemo.MovieDetailsPreviewActivity"
42+
android:parentActivityName=".ui.browse.LayoutBrowseActivity" />
4343
<activity
44-
android:name="com.hossainkhan.android.demo.ui.functionaldemo.TedTalkPlaybackActivity"
45-
android:parentActivityName="com.hossainkhan.android.demo.ui.browse.LayoutBrowseActivity" />
44+
android:name=".ui.functionaldemo.TedTalkPlaybackActivity"
45+
android:parentActivityName=".ui.browse.LayoutBrowseActivity" />
46+
<activity
47+
android:name=".ui.resource.LearningResourceActivity"
48+
android:parentActivityName=".ui.browse.LayoutBrowseActivity" />
4649
</application>
4750

4851
</manifest>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright (c) 2019 Hossain Khan
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.hossainkhan.android.demo.data
18+
19+
data class ItemModel(val id: Int)

app/src/main/java/com/hossainkhan/android/demo/data/LayoutDataStore.kt

+13-2
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,16 @@ class LayoutDataStore @Inject constructor(
197197
layoutResourceId = R.layout.demo_ted_talk_playback,
198198
thumbnailResourceId = R.drawable.ic_ted_talks_logo,
199199
title = "Demo: TED Talk Preview Screen",
200-
description = "A demo screen containing TED talks video playback screen with different controls.")
200+
description = "A demo screen containing TED talks video playback screen with different controls."),
201+
202+
/*
203+
* Additional resources to learn more about ConstraintLayout
204+
*/
205+
LayoutInformation(
206+
layoutResourceId = R.layout.activity_learning_resource,
207+
thumbnailResourceId = R.drawable.poster_angry_birds,
208+
title = "Resources",
209+
description = "XYZ")
201210

202211

203212
/*
@@ -223,7 +232,7 @@ class LayoutDataStore @Inject constructor(
223232
* Returns Github URL for layout resource file for this project.
224233
*
225234
* @param layoutResourceId The layout resource ID to generate the URL for.
226-
* @return The URL to load the layout blob file.
235+
* @return The URL to load the layout blob file. For example: https://github.com/amardeshbd/android-constraint-layout-cheatsheet/blob/master/app/src/main/res/layout/preview_dimension_ratio.xml
227236
*/
228237
fun getLayoutUrl(@LayoutRes layoutResourceId: Int): String {
229238
// Contains package name and layout name
@@ -234,6 +243,8 @@ class LayoutDataStore @Inject constructor(
234243
throw IllegalStateException("Only layout resource is allowed.")
235244
}
236245

246+
// Returns fully qualified URL that can be viewed online. For example:
247+
// https://github.com/amardeshbd/android-constraint-layout-cheatsheet/blob/master/app/src/main/res/layout/preview_dimension_ratio.xml
237248
return AppConfig.GITHUB_BASE_URL.plus("/blob/master/app/src/main/res/") +
238249
resourceName.split(':')
239250
.last().plus(".xml")

app/src/main/java/com/hossainkhan/android/demo/di/ActivityBindingModule.kt

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.hossainkhan.android.demo.ui.layoutpreview.LayoutGuidelineBarrierActiv
2424
import com.hossainkhan.android.demo.ui.layoutpreview.LayoutGuidelineGroupActivity
2525
import com.hossainkhan.android.demo.ui.layoutpreview.LayoutPreviewBaseActivity
2626
import com.hossainkhan.android.demo.ui.layoutpreview.LayoutVisibilityGoneActivity
27+
import com.hossainkhan.android.demo.ui.resource.LearningResourceActivity
2728
import dagger.Module
2829
import dagger.android.ContributesAndroidInjector
2930

@@ -83,4 +84,8 @@ abstract class ActivityBindingModule {
8384
@ActivityScope
8485
@ContributesAndroidInjector
8586
abstract fun layoutTedTalkPlaybackPreviewActivity(): TedTalkPlaybackActivity
87+
88+
@ActivityScope
89+
@ContributesAndroidInjector
90+
abstract fun learningResourceActivity(): LearningResourceActivity
8691
}

app/src/main/java/com/hossainkhan/android/demo/di/ViewModelModule.kt

+8-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import androidx.lifecycle.ViewModel
2020
import androidx.lifecycle.ViewModelProvider
2121
import com.hossainkhan.android.demo.ui.browse.LayoutBrowseViewModel
2222
import com.hossainkhan.android.demo.ui.layoutpreview.LayoutInfoViewModel
23+
import com.hossainkhan.android.demo.ui.resource.LearningResourceViewModel
2324
import com.hossainkhan.android.demo.viewmodel.ViewModelProviderFactory
2425
import dagger.Binds
2526
import dagger.Module
@@ -36,12 +37,17 @@ abstract class ViewModelModule {
3637
@Binds
3738
@IntoMap
3839
@ViewModelKey(LayoutBrowseViewModel::class)
39-
abstract fun bindLayoutBrowserViewModel(layoutBrowseViewModel: LayoutBrowseViewModel): ViewModel
40+
abstract fun bindLayoutBrowserViewModel(viewModel: LayoutBrowseViewModel): ViewModel
4041

4142
@Binds
4243
@IntoMap
4344
@ViewModelKey(LayoutInfoViewModel::class)
44-
abstract fun bindLayoutInfoViewModel(layoutInfoViewModel: LayoutInfoViewModel): ViewModel
45+
abstract fun bindLayoutInfoViewModel(viewModel: LayoutInfoViewModel): ViewModel
46+
47+
@Binds
48+
@IntoMap
49+
@ViewModelKey(LearningResourceViewModel::class)
50+
abstract fun bindResourceViewModel(viewModel: LearningResourceViewModel): ViewModel
4551

4652
@Binds
4753
abstract fun bindViewModelFactory(factory: ViewModelProviderFactory): ViewModelProvider.Factory

app/src/main/java/com/hossainkhan/android/demo/ui/browse/DefaultLayoutBrowseNavigator.kt

+7
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,11 @@ class DefaultLayoutBrowseNavigator @Inject constructor(private val context: Cont
3535
startIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
3636
context.startActivity(startIntent)
3737
}
38+
39+
override fun <T> loadActivity(clazz: Class<T>) {
40+
val startIntent = Intent(context, clazz)
41+
// FIX IT: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
42+
startIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
43+
context.startActivity(startIntent)
44+
}
3845
}

app/src/main/java/com/hossainkhan/android/demo/ui/browse/LayoutBrowseNavigator.kt

+1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ import androidx.annotation.LayoutRes
2424
interface LayoutBrowseNavigator {
2525
fun loadLayoutPreview(@LayoutRes layoutResId: Int)
2626
fun <T> loadLayoutPreview(clazz: Class<T>, @LayoutRes layoutResId: Int)
27+
fun <T> loadActivity(clazz: Class<T>)
2728
}

app/src/main/java/com/hossainkhan/android/demo/ui/browse/LayoutBrowseViewModel.kt

+4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import com.hossainkhan.android.demo.ui.layoutpreview.LayoutDimensionMinMaxActivi
2929
import com.hossainkhan.android.demo.ui.layoutpreview.LayoutGuidelineBarrierActivity
3030
import com.hossainkhan.android.demo.ui.layoutpreview.LayoutGuidelineGroupActivity
3131
import com.hossainkhan.android.demo.ui.layoutpreview.LayoutVisibilityGoneActivity
32+
import com.hossainkhan.android.demo.ui.resource.LearningResourceActivity
3233
import timber.log.Timber
3334
import javax.inject.Inject
3435

@@ -78,6 +79,9 @@ class LayoutBrowseViewModel @Inject constructor(
7879
R.layout.demo_ted_talk_playback -> {
7980
browseNavigator.loadLayoutPreview(TedTalkPlaybackActivity::class.java, layoutResId)
8081
}
82+
R.layout.activity_learning_resource -> {
83+
browseNavigator.loadActivity(LearningResourceActivity::class.java)
84+
}
8185
else -> {
8286
// By default it loads the preview activity with the layout requested.
8387
browseNavigator.loadLayoutPreview(layoutResId)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
* Copyright (c) 2019 Hossain Khan
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.hossainkhan.android.demo.ui.resource
18+
19+
import androidx.appcompat.app.AppCompatActivity
20+
import android.os.Bundle
21+
import androidx.databinding.DataBindingUtil
22+
import androidx.lifecycle.Observer
23+
import androidx.lifecycle.ViewModelProvider
24+
import androidx.recyclerview.widget.LinearLayoutManager
25+
import androidx.recyclerview.widget.RecyclerView
26+
import com.hossainkhan.android.demo.R
27+
import com.hossainkhan.android.demo.databinding.ActivityLearningResourceBinding
28+
import com.hossainkhan.android.demo.viewmodel.ViewModelProviderFactory
29+
import dagger.android.AndroidInjection
30+
import timber.log.Timber
31+
import javax.inject.Inject
32+
33+
class LearningResourceActivity : AppCompatActivity() {
34+
35+
@Inject
36+
internal lateinit var viewModelFactory: ViewModelProviderFactory
37+
private lateinit var viewModel: LearningResourceViewModel
38+
private lateinit var binding: ActivityLearningResourceBinding
39+
40+
41+
override fun onCreate(savedInstanceState: Bundle?) {
42+
AndroidInjection.inject(this)
43+
super.onCreate(savedInstanceState)
44+
binding = DataBindingUtil.setContentView(this, R.layout.activity_learning_resource)
45+
46+
viewModel = ViewModelProvider(this, viewModelFactory).get(LearningResourceViewModel::class.java)
47+
setupData(binding.recyclerView)
48+
}
49+
50+
51+
private fun setupData(ideaList: RecyclerView) {
52+
53+
val ideaListAdapter = ResourceListAdapter { data ->
54+
Timber.d("Item Clicked: $data")
55+
viewModel.onItemClicked(data)
56+
}
57+
58+
ideaList.apply {
59+
setHasFixedSize(false)
60+
layoutManager = LinearLayoutManager(this@LearningResourceActivity)
61+
adapter = ideaListAdapter
62+
}
63+
64+
viewModel.data.observe(this, Observer { result ->
65+
ideaListAdapter.submitList(result)
66+
})
67+
}
68+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (c) 2019 Hossain Khan
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.hossainkhan.android.demo.ui.resource
18+
19+
import androidx.lifecycle.LiveData
20+
import androidx.lifecycle.MutableLiveData
21+
import androidx.lifecycle.ViewModel
22+
import com.hossainkhan.android.demo.data.ItemModel
23+
import javax.inject.Inject
24+
25+
class LearningResourceViewModel @Inject constructor() : ViewModel() {
26+
private val _data = MutableLiveData<List<ItemModel>>()
27+
val data: LiveData<List<ItemModel>> = _data
28+
29+
private val sampleData = mutableListOf<ItemModel>()
30+
31+
init {
32+
generateSampleDataSet()
33+
_data.value = sampleData.toList()
34+
}
35+
36+
private fun generateSampleDataSet() {
37+
for (i in 1..20) {
38+
sampleData.add(ItemModel(i))
39+
}
40+
}
41+
42+
43+
44+
fun onItemClicked(item: ItemModel) {
45+
46+
}
47+
}

0 commit comments

Comments
 (0)