> liveData);
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kunminx/puremusic/domain/request/GridItemRequest.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.puremusic.domain.request;
4 |
5 | import androidx.lifecycle.LiveData;
6 | import androidx.lifecycle.MutableLiveData;
7 |
8 | import com.kunminx.puremusic.data.bean.GridItem;
9 | import com.kunminx.puremusic.data.repository.DataRepository;
10 |
11 | import java.util.List;
12 |
13 | /**
14 | * 音乐资源 Request
15 | *
16 | * TODO tip:Request 通常按业务划分
17 | * 一个项目中通常存在多个 Request
18 | *
19 | * request 的职责仅限于 数据请求,不建议在此处理 UI 逻辑,
20 | * UI 逻辑只适合在 Activity/Fragment 等视图控制器中完成,是 “数据驱动” 的一部分,
21 | * 将来升级到 Jetpack Compose 更是如此。
22 | *
23 | * 如果这样说还不理解的话,详见 https://xiaozhuanlan.com/topic/6257931840
24 | *
25 | * Create by KunMinX at 19/10/29
26 | */
27 | public class GridItemRequest implements Request.IGridItemRequest {
28 |
29 | private MutableLiveData> mJavaItemsLiveData;
30 | private MutableLiveData> mKotlinItemsLiveData;
31 |
32 | //TODO tip 向 ui 层提供的 request LiveData,使用抽象的 LiveData 而不是 MutableLiveData
33 | // 如此是为了来自数据层的数据,在 ui 层中只读,以避免团队新手不可预期的误用
34 |
35 | @Override
36 | public LiveData> getJavaItemsLiveData() {
37 | if (mJavaItemsLiveData == null) {
38 | mJavaItemsLiveData = new MutableLiveData<>();
39 | }
40 | return mJavaItemsLiveData;
41 | }
42 |
43 | @Override
44 | public LiveData> getKotlinItemsLiveData() {
45 | if (mKotlinItemsLiveData == null) {
46 | mKotlinItemsLiveData = new MutableLiveData<>();
47 | }
48 | return mKotlinItemsLiveData;
49 | }
50 |
51 | @Override
52 | public void requestJavaItems() {
53 | DataRepository.getInstance().getJavaItems(mJavaItemsLiveData);
54 | }
55 |
56 | @Override
57 | public void requestKotlinItems() {
58 | DataRepository.getInstance().getKotlinItems(mKotlinItemsLiveData);
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kunminx/puremusic/domain/request/Request.java:
--------------------------------------------------------------------------------
1 | package com.kunminx.puremusic.domain.request;
2 |
3 | import androidx.lifecycle.LiveData;
4 |
5 | import com.kunminx.puremusic.data.bean.GridItem;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | * Create by KunMinX at 2020/5/21
11 | */
12 | public class Request {
13 |
14 | public interface IGridItemRequest {
15 |
16 | LiveData> getJavaItemsLiveData();
17 |
18 | LiveData> getKotlinItemsLiveData();
19 |
20 | void requestJavaItems();
21 |
22 | void requestKotlinItems();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kunminx/puremusic/ui/adapter/GridItemAdapter.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.puremusic.ui.adapter;
4 |
5 | import android.content.Context;
6 |
7 | import androidx.annotation.NonNull;
8 | import androidx.recyclerview.widget.DiffUtil;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | import com.kunminx.architecture.ui.adapter.SimpleBindingAdapter;
12 | import com.kunminx.puremusic.R;
13 | import com.kunminx.puremusic.data.bean.GridItem;
14 | import com.kunminx.puremusic.databinding.AdapterGridItemBinding;
15 |
16 | /**
17 | * Create by KunMinX at 20/4/19
18 | */
19 | public class GridItemAdapter extends SimpleBindingAdapter {
20 |
21 | public GridItemAdapter(Context context) {
22 | super(context, R.layout.adapter_grid_item, new DiffUtil.ItemCallback() {
23 | @Override
24 | public boolean areItemsTheSame(@NonNull GridItem oldItem, @NonNull GridItem newItem) {
25 | return oldItem.equals(newItem);
26 | }
27 |
28 | @Override
29 | public boolean areContentsTheSame(@NonNull GridItem oldItem, @NonNull GridItem newItem) {
30 | return oldItem.getUuid().equals(newItem.getUuid());
31 | }
32 | });
33 | }
34 |
35 | @Override
36 | protected void onBindItem(AdapterGridItemBinding binding, GridItem item, RecyclerView.ViewHolder holder) {
37 | binding.setItem(item);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kunminx/puremusic/ui/page/MainActivity.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.puremusic.ui.page;
4 |
5 | import android.content.ComponentName;
6 | import android.content.Intent;
7 | import android.os.Bundle;
8 |
9 | import androidx.databinding.DataBindingUtil;
10 |
11 | import com.kunminx.architecture.ui.BaseActivity;
12 | import com.kunminx.puremusic.R;
13 | import com.kunminx.puremusic.databinding.ActivityMainBinding;
14 | import com.kunminx.puremusic.ui.adapter.GridItemAdapter;
15 | import com.kunminx.puremusic.ui.state.MainActivityViewModel;
16 |
17 | /**
18 | * Create by KunMinX at 19/10/16
19 | */
20 |
21 | public class MainActivity extends BaseActivity {
22 |
23 | private MainActivityViewModel mMainActivityViewModel;
24 |
25 | @Override
26 | protected void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | mMainActivityViewModel = getActivityScopeViewModel(MainActivityViewModel.class);
29 |
30 | ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
31 | binding.setVm(mMainActivityViewModel);
32 |
33 | GridItemAdapter adapterJava = new GridItemAdapter(getApplicationContext());
34 | adapterJava.setOnItemClickListener((item, position) -> {
35 | Intent intent = new Intent();
36 | intent.setComponent(new ComponentName(item.getPackageName(), item.getActivityPath()));
37 | startActivity(intent);
38 | });
39 | binding.setAdapterJava(adapterJava);
40 |
41 | GridItemAdapter adapterKotlin = new GridItemAdapter(getApplicationContext());
42 | adapterKotlin.setOnItemClickListener(((item, position) -> {
43 | Intent intent = new Intent();
44 | intent.setComponent(new ComponentName(item.getPackageName(), item.getActivityPath()));
45 | startActivity(intent);
46 | }));
47 | binding.setAdapterKotlin(adapterKotlin);
48 |
49 | mMainActivityViewModel.getJavaItemsLiveData().observe(this, gridItems -> {
50 | mMainActivityViewModel.javaList.setValue(gridItems);
51 | });
52 |
53 | mMainActivityViewModel.getKotlinItemsLiveData().observe(this, gridItems -> {
54 | mMainActivityViewModel.kotlinList.setValue(gridItems);
55 | });
56 |
57 | mMainActivityViewModel.requestJavaItems();
58 | mMainActivityViewModel.requestKotlinItems();
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/app/src/main/java/com/kunminx/puremusic/ui/state/MainActivityViewModel.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.puremusic.ui.state;
4 |
5 | import androidx.databinding.ObservableBoolean;
6 | import androidx.databinding.ObservableField;
7 | import androidx.lifecycle.LiveData;
8 | import androidx.lifecycle.MutableLiveData;
9 | import androidx.lifecycle.ViewModel;
10 |
11 | import com.kunminx.puremusic.data.bean.GridItem;
12 | import com.kunminx.puremusic.domain.request.GridItemRequest;
13 | import com.kunminx.puremusic.domain.request.Request;
14 |
15 | import java.util.List;
16 |
17 | /**
18 | * Create by KunMinX at 19/10/29
19 | */
20 | public class MainActivityViewModel extends ViewModel implements Request.IGridItemRequest {
21 |
22 | public final ObservableBoolean initTabAndPage = new ObservableBoolean();
23 |
24 | public final ObservableField pageAssetPath = new ObservableField<>();
25 |
26 | public final ObservableField homeImg = new ObservableField<>();
27 |
28 | public final MutableLiveData> javaList = new MutableLiveData<>();
29 | public final MutableLiveData> kotlinList = new MutableLiveData<>();
30 |
31 | private GridItemRequest mGridItemRequest = new GridItemRequest();
32 |
33 | {
34 | initTabAndPage.set(true);
35 | pageAssetPath.set("java2kotlin.html");
36 | homeImg.set("https://i.loli.net/2020/06/09/rLzKlThf5pQvtCj.jpg");
37 | }
38 |
39 | @Override
40 | public LiveData> getJavaItemsLiveData() {
41 | return mGridItemRequest.getJavaItemsLiveData();
42 | }
43 |
44 | @Override
45 | public LiveData> getKotlinItemsLiveData() {
46 | return mGridItemRequest.getKotlinItemsLiveData();
47 | }
48 |
49 | @Override
50 | public void requestJavaItems() {
51 | mGridItemRequest.requestJavaItems();
52 | }
53 |
54 | @Override
55 | public void requestKotlinItems() {
56 | mGridItemRequest.requestKotlinItems();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/app/src/main/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/bg_album_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/app/src/main/res/drawable-xxhdpi/bg_album_default.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/app/src/main/res/drawable-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/app/src/main/res/drawable-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/app/src/main/res/drawable/bg_home.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_menu_black_48dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_music_note_black_48dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_search_black_48dp.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/adapter_grid_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
22 |
23 |
36 |
37 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/navigation/nav_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
14 |
15 |
31 |
32 |
33 |
34 |
47 |
48 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 | #fff
8 | #000
9 | #666
10 | #999
11 | #00000000
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimen.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 55dp
5 | 200dp
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Jetpack from Java to Kotlin
3 | Java
4 | Kotlin
5 | About
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
--------------------------------------------------------------------------------
/app/src/test/java/com/kunminx/puremusic/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.kunminx.puremusic;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/architecture/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/architecture/build.gradle:
--------------------------------------------------------------------------------
1 | import com.flywith24.version_config.BuildConfig
2 | import com.flywith24.version_config.dependencies.AndroidX
3 | import com.flywith24.version_config.dependencies.Google
4 | import com.flywith24.version_config.dependencies.Testing
5 | import com.flywith24.version_config.dependencies.ThirdParty
6 |
7 |
8 | plugins {
9 | id "com.flywith24.version"
10 | }
11 |
12 | apply plugin: 'com.android.library'
13 | apply plugin: 'kotlin-android'
14 |
15 | android {
16 | compileSdkVersion BuildConfig.compileSdkVersion
17 | buildToolsVersion BuildConfig.buildToolsVersion
18 |
19 | defaultConfig {
20 | minSdkVersion BuildConfig.minSdkVersion
21 | targetSdkVersion BuildConfig.targetSdkVersion
22 | versionCode BuildConfig.versionCode
23 | versionName BuildConfig.versionName
24 |
25 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
26 | consumerProguardFiles 'consumer-rules.pro'
27 | }
28 |
29 | buildTypes {
30 | release {
31 | minifyEnabled false
32 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
33 | }
34 | }
35 |
36 | lintOptions {
37 | checkReleaseBuilds false
38 | abortOnError false
39 | }
40 |
41 | compileOptions {
42 | sourceCompatibility JavaVersion.VERSION_1_8
43 | targetCompatibility JavaVersion.VERSION_1_8
44 | }
45 |
46 | dataBinding {
47 | enabled = true
48 | }
49 |
50 | }
51 |
52 | dependencies {
53 | implementation fileTree(dir: 'libs', include: ['*.jar'])
54 |
55 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
56 |
57 | testImplementation(Testing.jUnit)
58 | androidTestImplementation(Testing.androidJunit)
59 | androidTestImplementation(Testing.androidRunner)
60 | androidTestImplementation(Testing.espresso)
61 |
62 | implementation(AndroidX.appcompat)
63 | implementation(AndroidX.constraintlayout)
64 | implementation(AndroidX.recyclerView)
65 | implementation(AndroidX.Fragment.fragment)
66 | implementation(Google.material)
67 |
68 | implementation(AndroidX.Lifecycle.lifecycleRuntime)
69 | implementation(AndroidX.Lifecycle.commonJava8)
70 | implementation(AndroidX.Lifecycle.extensions)
71 | implementation(AndroidX.Lifecycle.viewModel)
72 | implementation(AndroidX.Lifecycle.liveData)
73 |
74 | implementation(ThirdParty.Archi.unPeekLiveData)
75 |
76 | implementation(AndroidX.Navigation.runtime)
77 |
78 | implementation(ThirdParty.Glide.glide)
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/architecture/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/architecture/consumer-rules.pro
--------------------------------------------------------------------------------
/architecture/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/architecture/src/androidTest/java/com/kunminx/architecture/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture;
4 |
5 | import android.content.Context;
6 |
7 | import androidx.test.platform.app.InstrumentationRegistry;
8 | import androidx.test.ext.junit.runners.AndroidJUnit4;
9 |
10 | import org.junit.Test;
11 | import org.junit.runner.RunWith;
12 |
13 | import static org.junit.Assert.*;
14 |
15 | /**
16 | * Instrumented test, which will execute on an Android device.
17 | *
18 | * @see Testing documentation
19 | */
20 | @RunWith(AndroidJUnit4.class)
21 | public class ExampleInstrumentedTest {
22 | @Test
23 | public void useAppContext() {
24 | // Context of the app under test.
25 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
26 |
27 | assertEquals("com.kunminx.architecture.test", appContext.getPackageName());
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/architecture/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
16 |
19 |
20 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/BaseApplication.kt:
--------------------------------------------------------------------------------
1 | package com.kunminx.architecture
2 |
3 | import android.app.Application
4 |
5 | /**
6 | * @author Flywith24
7 | * @date 2020/5/30
8 | * time 20:43
9 | * description
10 | */
11 | open class BaseApplication : Application() {
12 | override fun onCreate() {
13 | super.onCreate()
14 | instance = this
15 | }
16 |
17 | companion object {
18 | @JvmStatic
19 | lateinit var instance: Application
20 | }
21 | }
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/data/manager/NetState.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.data.manager;
4 |
5 | /**
6 | * Create by KunMinX at 19/10/11
7 | */
8 | public class NetState {
9 |
10 | private String responseCode;
11 | private boolean success = true;
12 |
13 | public String getResponseCode() {
14 | return responseCode;
15 | }
16 |
17 | public void setResponseCode(String responseCode) {
18 | this.responseCode = responseCode;
19 | }
20 |
21 | public boolean isSuccess() {
22 | return success;
23 | }
24 |
25 | public void setSuccess(boolean success) {
26 | this.success = success;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/data/manager/NetworkStateManager.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.data.manager;
4 |
5 | import android.content.IntentFilter;
6 | import android.net.ConnectivityManager;
7 |
8 | import androidx.annotation.NonNull;
9 | import androidx.lifecycle.DefaultLifecycleObserver;
10 | import androidx.lifecycle.LifecycleOwner;
11 |
12 | import com.kunminx.architecture.ui.callback.ProtectedUnPeekLiveData;
13 | import com.kunminx.architecture.ui.callback.UnPeekLiveData;
14 | import com.kunminx.architecture.utils.Utils;
15 |
16 | /**
17 | * Create by KunMinX at 19/10/11
18 | */
19 | public class NetworkStateManager implements DefaultLifecycleObserver {
20 |
21 | private static final NetworkStateManager S_MANAGER = new NetworkStateManager();
22 | private UnPeekLiveData networkStateCallback;
23 | private NetworkStateReceive mNetworkStateReceive;
24 |
25 | private NetworkStateManager() {
26 | }
27 |
28 | public static NetworkStateManager getInstance() {
29 | return S_MANAGER;
30 | }
31 |
32 | public ProtectedUnPeekLiveData getNetworkStateCallback() {
33 | if (networkStateCallback == null) networkStateCallback = new UnPeekLiveData<>();
34 | return networkStateCallback;
35 | }
36 |
37 | @Override
38 | public void onResume(@NonNull LifecycleOwner owner) {
39 | mNetworkStateReceive = new NetworkStateReceive();
40 | IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
41 | Utils.getApp().getApplicationContext().registerReceiver(mNetworkStateReceive, filter);
42 | }
43 |
44 | @Override
45 | public void onPause(@NonNull LifecycleOwner owner) {
46 | if (mNetworkStateReceive != null) {
47 | Utils.getApp().getApplicationContext().unregisterReceiver(mNetworkStateReceive);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/data/manager/NetworkStateReceive.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.data.manager;
4 |
5 | import android.content.BroadcastReceiver;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.net.ConnectivityManager;
9 | import android.widget.Toast;
10 |
11 | import com.kunminx.architecture.R;
12 | import com.kunminx.architecture.utils.NetworkUtils;
13 |
14 | import java.util.Objects;
15 |
16 | /**
17 | * Create by KunMinX at 19/8/5
18 | */
19 | public class NetworkStateReceive extends BroadcastReceiver {
20 |
21 | @Override
22 | public void onReceive(Context context, Intent intent) {
23 | if (Objects.equals(intent.getAction(), ConnectivityManager.CONNECTIVITY_ACTION)) {
24 | if (!NetworkUtils.isConnected()) {
25 | Toast.makeText(context, context.getString(R.string.network_not_good), Toast.LENGTH_SHORT).show();
26 | }
27 | }
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/data/usecase/UseCase.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.data.usecase;
4 |
5 | /**
6 | * Use cases are the entry points to the domain layer.
7 | *
8 | * @param the request type
9 | * @param the response type
10 | */
11 | public abstract class UseCase {
12 |
13 | private Q mRequestValues;
14 |
15 | private UseCaseCallback mUseCaseCallback;
16 |
17 | public Q getRequestValues() {
18 | return mRequestValues;
19 | }
20 |
21 | public void setRequestValues(Q requestValues) {
22 | mRequestValues = requestValues;
23 | }
24 |
25 | public UseCaseCallback
getUseCaseCallback() {
26 | return mUseCaseCallback;
27 | }
28 |
29 | public void setUseCaseCallback(UseCaseCallback
useCaseCallback) {
30 | mUseCaseCallback = useCaseCallback;
31 | }
32 |
33 | void run() {
34 | executeUseCase(mRequestValues);
35 | }
36 |
37 | protected abstract void executeUseCase(Q requestValues);
38 |
39 | /**
40 | * Data passed to a request.
41 | */
42 | public interface RequestValues {
43 | }
44 |
45 | /**
46 | * Data received from a request.
47 | */
48 | public interface ResponseValue {
49 | }
50 |
51 | public interface UseCaseCallback {
52 | void onSuccess(R response);
53 |
54 | void onError();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/data/usecase/UseCaseScheduler.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.data.usecase;
4 |
5 | /**
6 | * Interface for schedulers, see {@link UseCaseThreadPoolScheduler}.
7 | */
8 | public interface UseCaseScheduler {
9 |
10 | void execute(Runnable runnable);
11 |
12 | void notifyResponse(final V response,
13 | final UseCase.UseCaseCallback useCaseCallback);
14 |
15 | void onError(
16 | final UseCase.UseCaseCallback useCaseCallback);
17 | }
18 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/data/usecase/UseCaseThreadPoolScheduler.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.data.usecase;
4 |
5 | import android.os.Handler;
6 |
7 | import java.util.concurrent.Executors;
8 | import java.util.concurrent.LinkedBlockingQueue;
9 | import java.util.concurrent.ThreadPoolExecutor;
10 | import java.util.concurrent.TimeUnit;
11 |
12 | /**
13 | * Executes asynchronous tasks using a {@link ThreadPoolExecutor}.
14 | *
15 | * See also {@link Executors} for a list of factory methods to create common
16 | * {@link java.util.concurrent.ExecutorService}s for different scenarios.
17 | */
18 | public class UseCaseThreadPoolScheduler implements UseCaseScheduler {
19 |
20 | public static final int POOL_SIZE = 2;
21 | public static final int MAX_POOL_SIZE = 4 * 2;
22 | public static final int FIXED_POOL_SIZE = 4;
23 | public static final int TIMEOUT = 30;
24 | final ThreadPoolExecutor mThreadPoolExecutor;
25 | private final Handler mHandler = new Handler();
26 |
27 | /**
28 | * 固定线程数的无界线程池
29 | */
30 | public UseCaseThreadPoolScheduler() {
31 | mThreadPoolExecutor = new ThreadPoolExecutor(FIXED_POOL_SIZE, FIXED_POOL_SIZE, TIMEOUT,
32 | TimeUnit.SECONDS, new LinkedBlockingQueue<>());
33 | }
34 |
35 | @Override
36 | public void execute(Runnable runnable) {
37 | mThreadPoolExecutor.execute(runnable);
38 | }
39 |
40 | @Override
41 | public void notifyResponse(final V response,
42 | final UseCase.UseCaseCallback useCaseCallback) {
43 | mHandler.post(() -> {
44 | if (null != useCaseCallback) {
45 | useCaseCallback.onSuccess(response);
46 | }
47 | });
48 | }
49 |
50 | @Override
51 | public void onError(
52 | final UseCase.UseCaseCallback useCaseCallback) {
53 | mHandler.post(useCaseCallback::onError);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/kotlin/Event.kt:
--------------------------------------------------------------------------------
1 | package com.kunminx.architecture.kotlin
2 |
3 | import androidx.lifecycle.ViewModelStore
4 |
5 | /**
6 | * @author Flywith24
7 | * @date 2020/6/4
8 | * time 21:10
9 | * description
10 | * 使用 包装类 解决 LiveData 粘性事件的问题
11 | * 详见 https://juejin.im/post/5b2b1b2cf265da5952314b63
12 | */
13 | open class Event(private val content: T) {
14 |
15 | var hasBeenHandled = false
16 | private set // Allow external read but not write
17 |
18 | private var map = HashMap()
19 |
20 | /**
21 | * Returns the content and prevents its use again.
22 | */
23 | fun getContentIfNotHandled(): T? {
24 | return if (hasBeenHandled) {
25 | null
26 | } else {
27 | hasBeenHandled = true
28 | content
29 | }
30 | }
31 |
32 | /**
33 | * 根据同观察者判断事件是否消费
34 | * 如果该观察者已消费数据,则返回null
35 | * 否则标记已消费并返回数据
36 | */
37 | fun getContentIfNotHandled(viewModelStore: ViewModelStore): T? {
38 | return if (map.contains(viewModelStore)) {
39 | null
40 | } else {
41 | map[viewModelStore] = true
42 | content
43 | }
44 | }
45 |
46 | /**
47 | * Returns the content, even if it's already been handled.
48 | */
49 | fun peekContent(): T = content
50 | }
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/kotlin/WrapperLiveData.kt:
--------------------------------------------------------------------------------
1 | package com.kunminx.architecture.kotlin
2 |
3 | import androidx.annotation.MainThread
4 | import androidx.lifecycle.*
5 |
6 | /**
7 | * @author Flywith24
8 | * @date 2020/6/4
9 | * time 21:13
10 | * description
11 | *
12 | * LiveData 包装类
13 | */
14 |
15 | //为 LiveData>提供类型别名,使用 EventLiveData 即可
16 | typealias EventMutableLiveData = MutableLiveData>
17 | typealias EventLiveData = LiveData>
18 |
19 | /**
20 | * 事件只能被唯一观察者消费
21 | */
22 | @MainThread
23 | inline fun EventMutableLiveData.observeEvent(
24 | owner: LifecycleOwner,
25 | crossinline onChanged: (T) -> Unit
26 | ): Observer> {
27 | val wrappedObserver = Observer> { t ->
28 | //数据没有被使用过则发送给调用者,否则不处理
29 | t.getContentIfNotHandled()?.let { data ->
30 | onChanged.invoke(data)
31 | }
32 | }
33 | observe(owner, wrappedObserver)
34 | return wrappedObserver
35 | }
36 |
37 | /**
38 | * 事件可被多个观察者消费,且每个观察者仅能消费一次
39 | */
40 | @MainThread
41 | inline fun EventMutableLiveData.observeEvent(
42 | owner: LifecycleOwner,
43 | viewModelStore: ViewModelStore,
44 | crossinline onChanged: (T) -> Unit
45 | ): Observer> {
46 | val wrappedObserver = Observer> { t ->
47 | //数据没有被使用过则发送给调用者,否则不处理
48 | t.getContentIfNotHandled(viewModelStore)?.let { data ->
49 | onChanged.invoke(data)
50 | }
51 | }
52 | observe(owner, wrappedObserver)
53 | return wrappedObserver
54 | }
55 |
56 | fun EventMutableLiveData.postEventValue(value: T) {
57 | postValue(Event(value))
58 | }
59 |
60 | fun EventMutableLiveData.setEventValue(value: T) {
61 | setValue(Event(value))
62 |
63 | }
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/ui/adapter/CommonViewPagerAdapter.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.ui.adapter;
4 |
5 |
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 |
9 | import androidx.annotation.NonNull;
10 | import androidx.annotation.Nullable;
11 | import androidx.viewpager.widget.PagerAdapter;
12 |
13 | /**
14 | * Create by KunMinX at 19/6/15
15 | */
16 | public class CommonViewPagerAdapter extends PagerAdapter {
17 |
18 | private final int count;
19 | private final boolean enableDestroyItem;
20 | private final String[] title;
21 |
22 | public CommonViewPagerAdapter(int count, boolean enableDestroyItem, String[] title) {
23 | this.count = count;
24 | this.enableDestroyItem = enableDestroyItem;
25 | this.title = title;
26 | }
27 |
28 | @Override
29 | public int getCount() {
30 | return count;
31 | }
32 |
33 | @Override
34 | public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
35 | return view == object;
36 | }
37 |
38 | @NonNull
39 | @Override
40 | public Object instantiateItem(@NonNull ViewGroup container, int position) {
41 | return container.getChildAt(position);
42 | }
43 |
44 | @Override
45 | public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
46 | if (enableDestroyItem) {
47 | container.removeView((View) object);
48 | }
49 | }
50 |
51 | @Nullable
52 | @Override
53 | public CharSequence getPageTitle(int position) {
54 | return title[position];
55 | }
56 | }
57 |
58 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/ui/adapter/SimpleBindingAdapter.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.ui.adapter;
4 |
5 | import android.content.Context;
6 |
7 | import androidx.annotation.LayoutRes;
8 | import androidx.annotation.NonNull;
9 | import androidx.databinding.ViewDataBinding;
10 | import androidx.recyclerview.widget.DiffUtil;
11 | import androidx.recyclerview.widget.RecyclerView;
12 |
13 | /**
14 | * @author KunMinX
15 | * Create at 2018/6/30
16 | */
17 | public abstract class SimpleBindingAdapter extends BaseBindingAdapter {
18 |
19 | private final int layout;
20 |
21 | public SimpleBindingAdapter(Context context, int layout, @NonNull DiffUtil.ItemCallback diffCallback) {
22 | super(context, diffCallback);
23 | this.layout = layout;
24 | }
25 |
26 | @Override
27 | protected @LayoutRes
28 | int getLayoutResId(int viewType) {
29 | return this.layout;
30 | }
31 |
32 | }
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/ui/binding_adapter/TabPageBindingAdapter.java:
--------------------------------------------------------------------------------
1 | package com.kunminx.architecture.ui.binding_adapter;
2 |
3 | import androidx.databinding.BindingAdapter;
4 | import androidx.viewpager.widget.ViewPager;
5 |
6 | import com.google.android.material.tabs.TabLayout;
7 | import com.kunminx.architecture.R;
8 | import com.kunminx.architecture.ui.adapter.CommonViewPagerAdapter;
9 |
10 | /**
11 | * Create by KunMinX at 2020/3/13
12 | */
13 | public class TabPageBindingAdapter {
14 |
15 | @BindingAdapter(value = {"initTabAndPage"}, requireAll = false)
16 | public static void initTabAndPage(TabLayout tabLayout, boolean initTabAndPage) {
17 | int count = tabLayout.getTabCount();
18 | String[] title = new String[count];
19 | for (int i = 0; i < count; i++) {
20 | TabLayout.Tab tab = tabLayout.getTabAt(i);
21 | if (tab != null && tab.getText() != null) {
22 | title[i] = tab.getText().toString();
23 | }
24 | }
25 | ViewPager viewPager = (tabLayout.getRootView()).findViewById(R.id.view_pager);
26 | if (viewPager != null) {
27 | viewPager.setAdapter(new CommonViewPagerAdapter(count, false, title));
28 | tabLayout.setupWithViewPager(viewPager);
29 | }
30 | }
31 |
32 | @BindingAdapter(value = {"tabSelectedListener"}, requireAll = false)
33 | public static void tabSelectedListener(TabLayout tabLayout, TabLayout.OnTabSelectedListener listener) {
34 | tabLayout.addOnTabSelectedListener(listener);
35 | }
36 |
37 | @BindingAdapter(value = {"setOffsetLimit"})
38 | public static void setOffsetLimit(ViewPager viewPager, int count) {
39 | viewPager.setOffscreenPageLimit(count);
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/ui/layout_manager/WrapContentGridLayoutManager.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.ui.layout_manager;
4 |
5 | import android.content.Context;
6 | import android.util.AttributeSet;
7 |
8 | import androidx.recyclerview.widget.GridLayoutManager;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | /**
12 | * Create by KunMinX at 2020/6/13
13 | */
14 | public class WrapContentGridLayoutManager extends GridLayoutManager {
15 |
16 | public WrapContentGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
17 | super(context, attrs, defStyleAttr, defStyleRes);
18 | }
19 |
20 | public WrapContentGridLayoutManager(Context context, int spanCount) {
21 | super(context, spanCount);
22 | }
23 |
24 | public WrapContentGridLayoutManager(Context context, int spanCount, int orientation, boolean reverseLayout) {
25 | super(context, spanCount, orientation, reverseLayout);
26 | }
27 |
28 | @Override
29 | public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
30 | try {
31 | super.onLayoutChildren(recycler, state);
32 | } catch (IndexOutOfBoundsException e) {
33 | e.printStackTrace();
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/ui/layout_manager/WrapContentLinearLayoutManager.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.ui.layout_manager;
4 |
5 | import android.content.Context;
6 | import android.util.AttributeSet;
7 |
8 | import androidx.recyclerview.widget.LinearLayoutManager;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | /**
12 | * Create by KunMinX at 2020/6/13
13 | */
14 | public class WrapContentLinearLayoutManager extends LinearLayoutManager {
15 | public WrapContentLinearLayoutManager(Context context) {
16 | super(context);
17 | }
18 |
19 | public WrapContentLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
20 | super(context, orientation, reverseLayout);
21 | }
22 |
23 | public WrapContentLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
24 | super(context, attrs, defStyleAttr, defStyleRes);
25 | }
26 |
27 | @Override
28 | public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
29 | try {
30 | super.onLayoutChildren(recycler, state);
31 | } catch (IndexOutOfBoundsException e) {
32 | e.printStackTrace();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/ui/layout_manager/WrapContentStaggeredGridLayoutManager.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.ui.layout_manager;
4 |
5 | import android.content.Context;
6 | import android.util.AttributeSet;
7 |
8 | import androidx.recyclerview.widget.RecyclerView;
9 | import androidx.recyclerview.widget.StaggeredGridLayoutManager;
10 |
11 | /**
12 | * Create by KunMinX at 2020/6/13
13 | */
14 | public class WrapContentStaggeredGridLayoutManager extends StaggeredGridLayoutManager {
15 |
16 | public WrapContentStaggeredGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
17 | super(context, attrs, defStyleAttr, defStyleRes);
18 | }
19 |
20 | public WrapContentStaggeredGridLayoutManager(int spanCount, int orientation) {
21 | super(spanCount, orientation);
22 | }
23 |
24 | @Override
25 | public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
26 | try {
27 | super.onLayoutChildren(recycler, state);
28 | } catch (IndexOutOfBoundsException e) {
29 | e.printStackTrace();
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/utils/DisplayUtils.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture.utils;
4 |
5 | /**
6 | * Create by KunMinX at 19/7/20
7 | */
8 |
9 | public class DisplayUtils {
10 |
11 | /**
12 | * convert px to its equivalent dp
13 | *
14 | * 将px转换为与之相等的dp
15 | */
16 | public static int px2dp(float pxValue) {
17 | final float scale = Utils.getApp().getResources().getDisplayMetrics().density;
18 | return (int) (pxValue / scale + 0.5f);
19 | }
20 |
21 |
22 | /**
23 | * convert dp to its equivalent px
24 | *
25 | * 将dp转换为与之相等的px
26 | */
27 | public static int dp2px(float dipValue) {
28 | final float scale = Utils.getApp().getResources().getDisplayMetrics().density;
29 | return (int) (dipValue * scale + 0.5f);
30 | }
31 |
32 |
33 | /**
34 | * convert px to its equivalent sp
35 | *
36 | * 将px转换为sp
37 | */
38 | public static int px2sp(float pxValue) {
39 | final float fontScale = Utils.getApp().getResources().getDisplayMetrics().scaledDensity;
40 | return (int) (pxValue / fontScale + 0.5f);
41 | }
42 |
43 |
44 | /**
45 | * convert sp to its equivalent px
46 | *
47 | * 将sp转换为px
48 | */
49 | public static int sp2px(float spValue) {
50 | final float fontScale = Utils.getApp().getResources().getDisplayMetrics().scaledDensity;
51 | return (int) (spValue * fontScale + 0.5f);
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/architecture/src/main/java/com/kunminx/architecture/utils/Etx.kt:
--------------------------------------------------------------------------------
1 | package com.kunminx.architecture.utils
2 |
3 | import android.widget.ImageView
4 | import com.bumptech.glide.Glide
5 |
6 | /**
7 | * @author Flywith24
8 | * @date 2020/5/30
9 | * time 20:53
10 | * description
11 | * 扩展函数
12 | */
13 |
14 | fun ImageView.loadImage(url: String) {
15 | Glide.with(context)
16 | .load(url)
17 | .into(this)
18 | }
--------------------------------------------------------------------------------
/architecture/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/architecture/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 网络不给力
6 |
7 |
8 |
--------------------------------------------------------------------------------
/architecture/src/main/res/values/values.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/architecture/src/main/res/xml/file_paths.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/architecture/src/test/java/com/kunminx/architecture/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.architecture;
4 |
5 | import org.junit.Test;
6 |
7 | import static org.junit.Assert.*;
8 |
9 | /**
10 | * Example local unit test, which will execute on the development machine (host).
11 | *
12 | * @see Testing documentation
13 | */
14 | public class ExampleUnitTest {
15 | @Test
16 | public void addition_isCorrect() {
17 | assertEquals(4, 2 + 2);
18 | }
19 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | ext {
5 | kotlin_version = '1.4.0'
6 | }
7 | repositories {
8 | google()
9 | maven { url 'https://maven.aliyun.com/repository/jcenter' }
10 | }
11 | dependencies {
12 | classpath 'com.android.tools.build:gradle:4.0.1'
13 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
14 | }
15 | }
16 |
17 | allprojects {
18 | repositories {
19 | google()
20 | maven { url 'https://maven.aliyun.com/repository/jcenter' }
21 | }
22 | }
23 |
24 | task clean(type: Delete) {
25 | delete rootProject.buildDir
26 | }
27 |
--------------------------------------------------------------------------------
/common_res/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/common_res/build.gradle:
--------------------------------------------------------------------------------
1 | import com.flywith24.version_config.BuildConfig
2 | import com.flywith24.version_config.dependencies.AndroidX
3 | import com.flywith24.version_config.dependencies.Google
4 |
5 | plugins {
6 | id "com.flywith24.version"
7 | }
8 | apply plugin: 'com.android.library'
9 | apply plugin: 'kotlin-android'
10 |
11 | android {
12 | compileSdkVersion BuildConfig.compileSdkVersion
13 | buildToolsVersion BuildConfig.buildToolsVersion
14 |
15 | defaultConfig {
16 | minSdkVersion BuildConfig.minSdkVersion
17 | targetSdkVersion BuildConfig.targetSdkVersion
18 | versionCode BuildConfig.versionCode
19 | versionName BuildConfig.versionName
20 |
21 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
22 | consumerProguardFiles "consumer-rules.pro"
23 | }
24 |
25 | buildTypes {
26 | release {
27 | minifyEnabled false
28 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
29 | }
30 | }
31 | }
32 |
33 | dependencies {
34 | implementation fileTree(dir: "libs", include: ["*.jar"])
35 | implementation(AndroidX.constraintlayout)
36 | implementation(AndroidX.recyclerView)
37 | implementation(AndroidX.appcompat)
38 | implementation(Google.material)
39 |
40 | }
--------------------------------------------------------------------------------
/common_res/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/consumer-rules.pro
--------------------------------------------------------------------------------
/common_res/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/common_res/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/common_res/src/main/res/anim/h_fragment_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
9 |
12 |
--------------------------------------------------------------------------------
/common_res/src/main/res/anim/h_fragment_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
8 |
--------------------------------------------------------------------------------
/common_res/src/main/res/anim/h_fragment_pop_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
--------------------------------------------------------------------------------
/common_res/src/main/res/anim/h_fragment_pop_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
7 |
8 |
11 |
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-anydpi/ic_add.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-anydpi/ic_back.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-anydpi/ic_menu_save.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-anydpi/round_solid_gray.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-hdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-hdpi/ic_add.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-hdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-hdpi/ic_back.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-hdpi/ic_menu_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-hdpi/ic_menu_save.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-mdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-mdpi/ic_add.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-mdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-mdpi/ic_back.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-mdpi/ic_menu_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-mdpi/ic_menu_save.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-xhdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-xhdpi/ic_add.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-xhdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-xhdpi/ic_back.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-xhdpi/ic_menu_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-xhdpi/ic_menu_save.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-xxhdpi/ic_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-xxhdpi/ic_add.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-xxhdpi/ic_back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-xxhdpi/ic_back.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable-xxhdpi/ic_menu_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/common_res/src/main/res/drawable-xxhdpi/ic_menu_save.png
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable/ripple_click.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
--------------------------------------------------------------------------------
/common_res/src/main/res/drawable/round_stroke_blue.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
--------------------------------------------------------------------------------
/common_res/src/main/res/menu/editor_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/common_res/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #000
5 | #ccc
6 | #55eeeeee
7 | #1E90FF
8 | #00000000
9 | #505b91
10 | #fff
11 |
--------------------------------------------------------------------------------
/common_res/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 测试 Lifecycles,请点击 \'添加定位\'
4 | 测试 LiveData,请点击 \'添加定位\'
5 | 添加定位
6 | 选择位置
7 | image
8 | 位置
9 | 动态列表
10 | 刚刚在B站发表了最新一期的视频讲解,感兴趣的小伙伴可前往查阅
11 |
12 | 请输入动态
13 | 发布动态
14 | ViewModel 组件示例 item 点击不提供跳转,下一个组件示例(DataBinding)提供跳转
15 | 保存
16 | Lifecycle 组件示例不提供保存功能,具体会在 DataBinding 组件示例开始提供
17 | liveData 组件示例不提供保存功能,具体会在 DataBinding 组件示例开始提供
18 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
20 | android.injected.testOnly=false
21 | android.databinding.incremental=true
22 | android.lifecycleProcessor.incremental=true
23 | kapt.incremental.apt=true
24 | kapt.use.worker.api=true
25 | kapt.include.compile.classpath=false
26 | org.gradle.parallel=true
27 | org.gradle.caching=true
28 | org.gradle.configureondemand=true
29 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Oct 16 14:42:29 CST 2019
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/jetpack_java/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/jetpack_java/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/jetpack_java/consumer-rules.pro
--------------------------------------------------------------------------------
/jetpack_java/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/jetpack_java/src/androidTest/java/com/kunminx/jetpack_java/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.kunminx.jetpack_java;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 |
25 | assertEquals("com.example.jetpack_java.test", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/common_data/APIs.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.common_data;
4 |
5 | /**
6 | * TODO:本示例专注于提供 Jetpack 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
7 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
8 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
9 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
10 | *
11 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
12 | *
13 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
14 | *
15 | *
16 | * Create by KunMinX at 2020/5/29
17 | */
18 | public class APIs {
19 |
20 | public static final String KUNMINX_URL = "https://upload.jianshu.io/users/upload_avatars/57036/3e7ae7bc-9b9b-46c8-8082-bb2481d979dc.jpg";
21 |
22 | public static final String FLYWITH24_URL = "https://upload-images.jianshu.io/upload_images/57036-48e9886afe74ea9b.jpeg";
23 |
24 | public static final String SCENE_URL = "https://upload-images.jianshu.io/upload_images/57036-99344035bfce65b8.jpeg";
25 |
26 | public static final String ADD_PIC_TIP_URL = "https://upload-images.jianshu.io/upload_images/57036-0c120ced543d506a.png";
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/common_data/Configs.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.common_data;
4 |
5 | /**
6 | * TODO:本示例专注于提供 Jetpack 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
7 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
8 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
9 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
10 | *
11 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
12 | *
13 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
14 | *
15 | *
16 | * Create by KunMinX at 2020/5/30
17 | */
18 | public class Configs {
19 |
20 | public final static int REQUEST_LOCATION_INFO = 0x00001;
21 | public final static int REQUEST_NEW_MOMENT = 0x00002;
22 | public final static String NEW_MOMENT = "NEW_MOMENT";
23 | public final static String LOCATION_RESULT = "LOCATION_RESULT";
24 | public final static String THIS_MOMENT = "THIS_MOMENT";
25 | }
26 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/common_data/bean/LocationBean.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.common_data.bean;
4 |
5 |
6 | /**
7 | * TODO:本示例专注于提供 Jetpack 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
8 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
9 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
10 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
11 | *
12 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
13 | *
14 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
15 | *
16 | *
17 | * Create by KunMinX at 2020/5/29
18 | */
19 | public class LocationBean {
20 |
21 | private String locationName;
22 |
23 | public LocationBean(String locationName) {
24 | this.locationName = locationName;
25 | }
26 |
27 | public String getLocationName() {
28 | return locationName;
29 | }
30 |
31 | public void setLocationName(String locationName) {
32 | this.locationName = locationName;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/common_ui/adapter/DiffUtilCallbacks.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.common_ui.adapter;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.recyclerview.widget.DiffUtil;
7 |
8 | import com.kunminx.jetpack_java.common_data.bean.LocationBean;
9 | import com.kunminx.jetpack_java.common_data.bean.Moment;
10 |
11 | /**
12 | * TODO:本示例专注于提供 Jetpack 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
13 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
14 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
15 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
16 | *
17 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
18 | *
19 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
20 | *
21 | *
22 | * Create by KunMinX at 2020/6/1
23 | */
24 | public class DiffUtilCallbacks {
25 |
26 | public DiffUtil.ItemCallback getLocationBeanItemCallback() {
27 | return new DiffUtil.ItemCallback() {
28 | @Override
29 | public boolean areItemsTheSame(@NonNull LocationBean oldItem, @NonNull LocationBean newItem) {
30 | return oldItem.equals(newItem);
31 | }
32 |
33 | @Override
34 | public boolean areContentsTheSame(@NonNull LocationBean oldItem, @NonNull LocationBean newItem) {
35 | return oldItem.getLocationName().equals(newItem.getLocationName());
36 | }
37 | };
38 | }
39 |
40 | public DiffUtil.ItemCallback getMomentItemCallback() {
41 | return new DiffUtil.ItemCallback() {
42 | @Override
43 | public boolean areItemsTheSame(@NonNull Moment oldItem, @NonNull Moment newItem) {
44 | return oldItem.equals(newItem);
45 | }
46 |
47 | @Override
48 | public boolean areContentsTheSame(@NonNull Moment oldItem, @NonNull Moment newItem) {
49 | return oldItem.getUuid().equals(newItem.getUuid());
50 | }
51 | };
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_01_lifecycles/ui/LifecycleLocationActivity.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_01_lifecycles.ui;
4 |
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 |
8 | import androidx.appcompat.widget.Toolbar;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | import com.kunminx.architecture.ui.BaseActivity;
12 | import com.kunminx.architecture.ui.layout_manager.WrapContentLinearLayoutManager;
13 | import com.kunminx.jetpack_java.R;
14 | import com.kunminx.jetpack_java.common_data.Configs;
15 | import com.kunminx.jetpack_java.common_ui.adapter.LocationAdapter;
16 | import com.kunminx.jetpack_java.sample_01_lifecycles.domain.LifecycleLocationManager;
17 |
18 | /**
19 | * TODO:本示例专注于提供 Lifecycle 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
20 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
21 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
22 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
23 | *
24 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
25 | *
26 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
27 | *
28 | *
29 | * Create by KunMinX at 19/10/16
30 | */
31 |
32 | public class LifecycleLocationActivity extends BaseActivity {
33 |
34 | private RecyclerView mRecyclerView;
35 | private Toolbar mToolbar;
36 | private LocationAdapter mLocationAdapter;
37 |
38 | @Override
39 | protected void onCreate(Bundle savedInstanceState) {
40 | super.onCreate(savedInstanceState);
41 |
42 | setContentView(R.layout.activity_location_lifecycles);
43 | mToolbar = findViewById(R.id.toolbar);
44 | mToolbar.setNavigationOnClickListener(v -> finish());
45 |
46 | mRecyclerView = findViewById(R.id.rv);
47 | mRecyclerView.setLayoutManager(new WrapContentLinearLayoutManager(getApplicationContext()));
48 |
49 | mRecyclerView.setAdapter(mLocationAdapter = new LocationAdapter(getApplicationContext(), locationBean -> {
50 | Intent intent = new Intent();
51 | intent.putExtra(Configs.LOCATION_RESULT, locationBean.getLocationName());
52 | setResult(RESULT_OK, intent);
53 | finish();
54 | }));
55 |
56 | getLifecycle().addObserver(LifecycleLocationManager.getInstance());
57 |
58 | LifecycleLocationManager.getInstance().setILocationCallback(list -> {
59 | runOnUiThread(() -> {
60 | mLocationAdapter.submitList(list);
61 | });
62 | });
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_02_livedata/domain/LiveDataLocationManager.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_02_livedata.domain;
4 |
5 | import androidx.annotation.NonNull;
6 | import androidx.lifecycle.DefaultLifecycleObserver;
7 | import androidx.lifecycle.LifecycleOwner;
8 | import androidx.lifecycle.LiveData;
9 | import androidx.lifecycle.MutableLiveData;
10 |
11 | import com.kunminx.jetpack_java.common_data.bean.LocationBean;
12 |
13 | import java.util.ArrayList;
14 | import java.util.List;
15 | import java.util.Timer;
16 | import java.util.TimerTask;
17 |
18 | /**
19 | * TODO:本示例专注于提供 LiveData 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
20 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
21 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
22 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
23 | *
24 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
25 | *
26 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
27 | *
28 | *
29 | *
30 | * Create by KunMinX at 2020/5/30
31 | */
32 | public class LiveDataLocationManager implements DefaultLifecycleObserver {
33 |
34 | private static LiveDataLocationManager sManager = new LiveDataLocationManager();
35 |
36 | private Timer mTimer;
37 |
38 | public static LiveDataLocationManager getInstance() {
39 | return sManager;
40 | }
41 |
42 | private LiveDataLocationManager() {
43 | }
44 |
45 | private MutableLiveData> mLocationBeans = new MutableLiveData<>();
46 |
47 | private List mList = new ArrayList<>();
48 |
49 | public LiveData> getLocationBeans() {
50 | return mLocationBeans;
51 | }
52 |
53 | @Override
54 | public void onResume(@NonNull LifecycleOwner owner) {
55 | //TODO 我是获取附近位置列表信息的后台定位服务,我耗电巨大,我随着页面的 onResume 开启了
56 |
57 | mTimer = new Timer();
58 |
59 | TimerTask task = new TimerTask() {
60 | @Override
61 | public void run() {
62 |
63 | //模拟定位,假设开启了 GPS 并且每秒获取若干条新的位置信息
64 |
65 | mList.add(new LocationBean("台北夜市 " + System.currentTimeMillis() + " 号"));
66 | mLocationBeans.postValue(mList);
67 |
68 | onResume(owner);
69 | }
70 | };
71 |
72 | mTimer.schedule(task, 200);
73 |
74 | }
75 |
76 | @Override
77 | public void onPause(@NonNull LifecycleOwner owner) {
78 | //TODO 定位服务随着页面的 onPause 而关闭了
79 |
80 | mTimer.cancel();
81 | mTimer = null;
82 |
83 | mList.clear();
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_02_livedata/ui/LiveDataLocationActivity.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_02_livedata.ui;
4 |
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 |
8 | import androidx.appcompat.widget.Toolbar;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | import com.kunminx.architecture.ui.BaseActivity;
12 | import com.kunminx.architecture.ui.layout_manager.WrapContentLinearLayoutManager;
13 | import com.kunminx.jetpack_java.R;
14 | import com.kunminx.jetpack_java.common_data.Configs;
15 | import com.kunminx.jetpack_java.common_ui.adapter.LocationAdapter;
16 | import com.kunminx.jetpack_java.sample_02_livedata.domain.LiveDataLocationManager;
17 |
18 | /**
19 | * TODO:本示例专注于提供 LiveData 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
20 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
21 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
22 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
23 | *
24 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
25 | *
26 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
27 | *
28 | *
29 | * Create by KunMinX at 19/10/16
30 | */
31 |
32 | public class LiveDataLocationActivity extends BaseActivity {
33 |
34 | private RecyclerView mRecyclerView;
35 | private Toolbar mToolbar;
36 |
37 | private LocationAdapter mLocationAdapter;
38 |
39 | @Override
40 | protected void onCreate(Bundle savedInstanceState) {
41 | super.onCreate(savedInstanceState);
42 |
43 | setContentView(R.layout.activity_location_lifecycles);
44 | mToolbar = findViewById(R.id.toolbar);
45 | mToolbar.setNavigationOnClickListener(v -> finish());
46 |
47 | mRecyclerView = findViewById(R.id.rv);
48 | mRecyclerView.setLayoutManager(new WrapContentLinearLayoutManager(getApplicationContext()));
49 |
50 | mRecyclerView.setAdapter(mLocationAdapter = new LocationAdapter(getApplicationContext(), locationBean -> {
51 | Intent intent = new Intent();
52 | intent.putExtra(Configs.LOCATION_RESULT, locationBean.getLocationName());
53 | setResult(RESULT_OK, intent);
54 | finish();
55 | }));
56 |
57 | getLifecycle().addObserver(LiveDataLocationManager.getInstance());
58 |
59 | LiveDataLocationManager.getInstance().getLocationBeans().observe(this, locationBeans -> {
60 | mLocationAdapter.submitList(locationBeans);
61 | });
62 |
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_03_viewmodel/domain/BaseRequest.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_03_viewmodel.domain;
4 |
5 | import androidx.lifecycle.LiveData;
6 |
7 | import com.kunminx.jetpack_java.common_data.bean.Moment;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | * TODO:本示例专注于提供 ViewModel 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
13 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
14 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
15 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
16 | *
17 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
18 | *
19 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
20 | *
21 | *
22 | * Create by KunMinX at 2020/5/30
23 | */
24 | public class BaseRequest {
25 |
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_03_viewmodel/domain/MomentRequest.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_03_viewmodel.domain;
4 |
5 | import androidx.lifecycle.LiveData;
6 | import androidx.lifecycle.MutableLiveData;
7 |
8 | import com.kunminx.jetpack_java.sample_03_viewmodel.data.DataRepository;
9 | import com.kunminx.jetpack_java.common_data.bean.Moment;
10 |
11 | import java.util.List;
12 |
13 | /**
14 | * TODO:本示例专注于提供 ViewModel 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
15 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
16 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
17 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
18 | *
19 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
20 | *
21 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
22 | *
23 | *
24 | * Create by KunMinX at 2020/5/30
25 | */
26 | public class MomentRequest extends BaseRequest {
27 |
28 | private MutableLiveData> mListMutableLiveData;
29 |
30 | public LiveData> getListMutableLiveData() {
31 | if (mListMutableLiveData == null) {
32 | mListMutableLiveData = new MutableLiveData<>();
33 | }
34 | return mListMutableLiveData;
35 | }
36 |
37 | public void requestList() {
38 | DataRepository.getInstance().requestList(mListMutableLiveData);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_03_viewmodel/ui/ViewModelListActivity.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_03_viewmodel.ui;
4 |
5 | import android.os.Bundle;
6 |
7 | import androidx.appcompat.widget.Toolbar;
8 | import androidx.recyclerview.widget.RecyclerView;
9 |
10 | import com.kunminx.architecture.ui.BaseActivity;
11 | import com.kunminx.architecture.ui.layout_manager.WrapContentLinearLayoutManager;
12 | import com.kunminx.jetpack_java.R;
13 | import com.kunminx.jetpack_java.common_ui.adapter.MomentAdapter;
14 | import com.kunminx.jetpack_java.sample_03_viewmodel.ui.state.ListViewModel;
15 |
16 | /**
17 | * TODO:本示例专注于提供 ViewModel 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
18 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
19 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
20 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
21 | *
22 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
23 | *
24 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
25 | *
26 | *
27 | * Create by KunMinX at 19/10/16
28 | */
29 |
30 | public class ViewModelListActivity extends BaseActivity {
31 |
32 | private ListViewModel mListViewModel;
33 | private RecyclerView mRecyclerView;
34 | private Toolbar mToolbar;
35 | private MomentAdapter mMomentAdapter;
36 |
37 | @Override
38 | protected void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | mListViewModel = getActivityScopeViewModel(ListViewModel.class);
41 |
42 | setContentView(R.layout.activity_list_viewmodel);
43 | mToolbar = findViewById(R.id.toolbar);
44 | mToolbar.setNavigationOnClickListener(v -> finish());
45 |
46 | mRecyclerView = findViewById(R.id.rv);
47 | mRecyclerView.setLayoutManager(new WrapContentLinearLayoutManager(getApplicationContext()));
48 |
49 | mRecyclerView.setAdapter(mMomentAdapter = new MomentAdapter(getApplicationContext(), moment -> {
50 | showLongToast(getString(R.string.viewmodel_item_click_tip));
51 | }));
52 |
53 | mListViewModel.momentRequest.getListMutableLiveData().observe(this, moments -> {
54 | mMomentAdapter.submitList(moments);
55 | });
56 |
57 | mListViewModel.momentRequest.requestList();
58 |
59 | }
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_03_viewmodel/ui/state/ListViewModel.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_03_viewmodel.ui.state;
4 |
5 | import androidx.lifecycle.LiveData;
6 | import androidx.lifecycle.ViewModel;
7 |
8 | import com.kunminx.jetpack_java.common_data.bean.Moment;
9 | import com.kunminx.jetpack_java.sample_03_viewmodel.domain.MomentRequest;
10 | import com.kunminx.jetpack_java.sample_03_viewmodel.domain.BaseRequest;
11 |
12 | import java.util.List;
13 |
14 | /**
15 | * TODO:本示例专注于提供 ViewModel 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
16 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
17 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
18 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
19 | *
20 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
21 | *
22 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
23 | *
24 | *
25 | * Create by KunMinX at 2020/5/30
26 | */
27 | public class ListViewModel extends ViewModel {
28 |
29 | public final MomentRequest momentRequest = new MomentRequest();
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_04_databinding/ui/DataBindingDetailActivity.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_04_databinding.ui;
4 |
5 | import android.os.Bundle;
6 |
7 | import androidx.databinding.DataBindingUtil;
8 |
9 | import com.kunminx.architecture.ui.BaseActivity;
10 | import com.kunminx.jetpack_java.R;
11 | import com.kunminx.jetpack_java.common_data.Configs;
12 | import com.kunminx.jetpack_java.common_data.bean.Moment;
13 | import com.kunminx.jetpack_java.databinding.ActivityDetailDatabindingBinding;
14 | import com.kunminx.jetpack_java.sample_04_databinding.ui.state.DetailViewModel;
15 |
16 | /**
17 | * TODO:本示例专注于提供 DataBinding 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
18 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
19 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
20 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
21 | *
22 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
23 | *
24 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
25 | *
26 | *
27 | * Create by KunMinX at 19/10/16
28 | */
29 |
30 | public class DataBindingDetailActivity extends BaseActivity {
31 |
32 | private DetailViewModel mDetailViewModel;
33 |
34 | @Override
35 | protected void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | mDetailViewModel = getActivityScopeViewModel(DetailViewModel.class);
38 |
39 | ActivityDetailDatabindingBinding binding =
40 | DataBindingUtil.setContentView(this, R.layout.activity_detail_databinding);
41 | binding.setLifecycleOwner(this);
42 | binding.setVm(mDetailViewModel);
43 | binding.setClick(new ClickProxy());
44 |
45 | Moment moment = (Moment) getIntent().getParcelableExtra(Configs.THIS_MOMENT);
46 | mDetailViewModel.initState(moment);
47 |
48 | }
49 |
50 | public class ClickProxy {
51 | public void back() {
52 | finish();
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_04_databinding/ui/adapter/DataBindingLocationAdapter.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_04_databinding.ui.adapter;
4 |
5 | import android.content.Context;
6 |
7 | import androidx.annotation.NonNull;
8 | import androidx.recyclerview.widget.DiffUtil;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | import com.kunminx.jetpack_java.R;
12 | import com.kunminx.jetpack_java.common_data.bean.LocationBean;
13 | import com.kunminx.jetpack_java.common_ui.adapter.DiffUtilCallbacks;
14 | import com.kunminx.jetpack_java.databinding.AdapterLocationDatabindingBinding;
15 | import com.kunminx.architecture.ui.adapter.SimpleBindingAdapter;
16 |
17 | /**
18 | * TODO:本示例专注于提供 DataBinding 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
19 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
20 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
21 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
22 | *
23 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
24 | *
25 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
26 | *
27 | *
28 | * Create by KunMinX at 2020/5/31
29 | */
30 | public class DataBindingLocationAdapter extends SimpleBindingAdapter {
31 |
32 | public DataBindingLocationAdapter(Context context) {
33 | super(context, R.layout.adapter_location_databinding, new DiffUtilCallbacks().getLocationBeanItemCallback());
34 | }
35 |
36 | @Override
37 | protected void onBindItem(AdapterLocationDatabindingBinding binding, LocationBean item, RecyclerView.ViewHolder holder) {
38 | binding.setBean(item);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_04_databinding/ui/adapter/DataBindingMomentAdapter.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_04_databinding.ui.adapter;
4 |
5 | import android.content.Context;
6 |
7 | import androidx.annotation.NonNull;
8 | import androidx.recyclerview.widget.DiffUtil;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | import com.kunminx.jetpack_java.R;
12 | import com.kunminx.jetpack_java.common_data.bean.Moment;
13 | import com.kunminx.jetpack_java.common_ui.adapter.DiffUtilCallbacks;
14 | import com.kunminx.jetpack_java.databinding.AdapterMomentDatabindingBinding;
15 | import com.kunminx.architecture.ui.adapter.SimpleBindingAdapter;
16 |
17 | /**
18 | * TODO:本示例专注于提供 DataBinding 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
19 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
20 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
21 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
22 | *
23 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
24 | *
25 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
26 | *
27 | *
28 | * Create by KunMinX at 2020/5/31
29 | */
30 | public class DataBindingMomentAdapter extends SimpleBindingAdapter {
31 |
32 | public DataBindingMomentAdapter(Context context) {
33 | super(context, R.layout.adapter_moment_databinding, new DiffUtilCallbacks().getMomentItemCallback());
34 | }
35 |
36 | @Override
37 | protected void onBindItem(AdapterMomentDatabindingBinding binding, Moment item, RecyclerView.ViewHolder holder) {
38 | binding.setMoment(item);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_04_databinding/ui/state/DetailViewModel.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_04_databinding.ui.state;
4 |
5 | import androidx.databinding.ObservableField;
6 | import androidx.lifecycle.ViewModel;
7 |
8 | import com.kunminx.jetpack_java.common_data.bean.Moment;
9 |
10 | /**
11 | * TODO:本示例专注于提供 DataBinding 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
12 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
13 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
14 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
15 | *
16 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
17 | *
18 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
19 | *
20 | *
21 | * Create by KunMinX at 2020/5/30
22 | */
23 | public class DetailViewModel extends ViewModel {
24 |
25 | public final ObservableField imgUrl = new ObservableField<>();
26 | public final ObservableField name = new ObservableField<>();
27 | public final ObservableField content = new ObservableField<>();
28 | public final ObservableField location = new ObservableField<>();
29 | public final ObservableField avatar = new ObservableField<>();
30 |
31 | public void initState(Moment moment) {
32 | avatar.set(moment.getUserAvatar());
33 | name.set(moment.getUserName());
34 | content.set(moment.getContent());
35 | imgUrl.set(moment.getImgUrl());
36 | location.set(moment.getLocation());
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_04_databinding/ui/state/EditorViewModel.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_04_databinding.ui.state;
4 |
5 | import androidx.databinding.ObservableField;
6 | import androidx.lifecycle.ViewModel;
7 |
8 | import com.kunminx.jetpack_java.common_data.APIs;
9 |
10 | /**
11 | * TODO:本示例专注于提供 DataBinding 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
12 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
13 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
14 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
15 | *
16 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
17 | *
18 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
19 | *
20 | *
21 | * Create by KunMinX at 2020/5/30
22 | */
23 | public class EditorViewModel extends ViewModel {
24 |
25 | public final ObservableField imgUrl = new ObservableField<>();
26 | public final ObservableField content = new ObservableField<>();
27 | public final ObservableField location = new ObservableField<>();
28 |
29 | {
30 | location.set("添加定位");
31 | content.set("");
32 | imgUrl.set(APIs.ADD_PIC_TIP_URL);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_04_databinding/ui/state/ListViewModel.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_04_databinding.ui.state;
4 |
5 | import androidx.lifecycle.LiveData;
6 | import androidx.lifecycle.MutableLiveData;
7 | import androidx.lifecycle.ViewModel;
8 |
9 | import com.kunminx.jetpack_java.common_data.bean.Moment;
10 | import com.kunminx.jetpack_java.sample_03_viewmodel.domain.MomentRequest;
11 |
12 | import java.util.List;
13 |
14 | /**
15 | * TODO:本示例专注于提供 DataBinding 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
16 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
17 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
18 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
19 | *
20 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
21 | *
22 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
23 | *
24 | *
25 | * Create by KunMinX at 2020/5/30
26 | */
27 | public class ListViewModel extends ViewModel {
28 |
29 | public final MutableLiveData> list = new MutableLiveData<>();
30 |
31 | public final MutableLiveData autoScrollToTopWhenInsert = new MutableLiveData<>(true);
32 |
33 | public final MomentRequest momentRequest = new MomentRequest();
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_04_databinding/ui/state/LocationViewModel.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_04_databinding.ui.state;
4 |
5 | import androidx.lifecycle.MutableLiveData;
6 | import androidx.lifecycle.ViewModel;
7 |
8 | import com.kunminx.jetpack_java.common_data.bean.LocationBean;
9 |
10 | import java.util.List;
11 |
12 | /**
13 | * TODO:本示例专注于提供 DataBinding 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
14 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
15 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
16 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
17 | *
18 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
19 | *
20 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
21 | *
22 | *
23 | * Create by KunMinX at 2020/5/30
24 | */
25 | public class LocationViewModel extends ViewModel {
26 |
27 | public final MutableLiveData> list = new MutableLiveData<>();
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_05_navigation/ui/NavigationDetailFragment.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_05_navigation.ui;
4 |
5 | import android.os.Bundle;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import androidx.annotation.NonNull;
11 | import androidx.annotation.Nullable;
12 |
13 | import com.kunminx.jetpack_java.R;
14 | import com.kunminx.jetpack_java.common_data.Configs;
15 | import com.kunminx.jetpack_java.common_data.bean.Moment;
16 | import com.kunminx.jetpack_java.databinding.FragmentDetailNavigationBinding;
17 | import com.kunminx.jetpack_java.sample_04_databinding.ui.state.DetailViewModel;
18 | import com.kunminx.architecture.ui.BaseFragment;
19 |
20 | /**
21 | * TODO:本示例专注于提供 Navigation 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
22 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
23 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
24 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
25 | *
26 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
27 | *
28 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
29 | *
30 | *
31 | * Create by KunMinX at 2020/5/30
32 | */
33 | public class NavigationDetailFragment extends BaseFragment {
34 |
35 | private DetailViewModel mDetailState;
36 |
37 | @Override
38 | public void onCreate(@Nullable Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | mDetailState = getFragmentScopeViewModel(DetailViewModel.class);
41 | }
42 |
43 | @Nullable
44 | @Override
45 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
46 | View view = inflater.inflate(R.layout.fragment_detail_navigation, container, false);
47 | FragmentDetailNavigationBinding binding = FragmentDetailNavigationBinding.bind(view);
48 | binding.setLifecycleOwner(this);
49 | binding.setVm(mDetailState);
50 | binding.setClick(new ClickProxy());
51 | return view;
52 | }
53 |
54 | @Override
55 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
56 | super.onViewCreated(view, savedInstanceState);
57 |
58 | Moment moment = (Moment) getArguments().getParcelable(Configs.THIS_MOMENT);
59 | mDetailState.initState(moment);
60 | }
61 |
62 | public class ClickProxy {
63 | public void back() {
64 | nav().navigateUp();
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_05_navigation/ui/NavigationMainActivity.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_05_navigation.ui;
4 |
5 | import android.os.Bundle;
6 |
7 | import androidx.databinding.DataBindingUtil;
8 |
9 | import com.kunminx.architecture.ui.BaseActivity;
10 | import com.kunminx.jetpack_java.R;
11 | import com.kunminx.jetpack_java.sample_05_navigation.ui.callback.SharedViewModel;
12 |
13 | /**
14 | * TODO:本示例专注于提供 Navigation 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
15 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
16 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
17 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
18 | *
19 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
20 | *
21 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
22 | *
23 | *
24 | * Create by KunMinX at 19/10/16
25 | */
26 |
27 | public class NavigationMainActivity extends BaseActivity {
28 |
29 | private SharedViewModel mPageCallback;
30 |
31 | @Override
32 | protected void onCreate(Bundle savedInstanceState) {
33 | super.onCreate(savedInstanceState);
34 |
35 | mPageCallback = getActivityScopeViewModel(SharedViewModel.class);
36 |
37 | DataBindingUtil.setContentView(this, R.layout.activity_main_navigation);
38 |
39 | mPageCallback.getCloseActivity().observeInActivity(this, aBoolean -> {
40 | finish();
41 | });
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_05_navigation/ui/callback/SharedViewModel.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_05_navigation.ui.callback;
4 |
5 | import androidx.lifecycle.ViewModel;
6 |
7 | import com.kunminx.architecture.ui.callback.ProtectedUnPeekLiveData;
8 | import com.kunminx.architecture.ui.callback.UnPeekLiveData;
9 | import com.kunminx.jetpack_java.common_data.bean.Moment;
10 |
11 | /**
12 | * TODO:本示例专注于提供 Navigation 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
13 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
14 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
15 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
16 | *
17 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
18 | *
19 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
20 | *
21 | *
22 | * Create by KunMinX at 2020/5/30
23 | */
24 | public class SharedViewModel extends ViewModel {
25 |
26 | private UnPeekLiveData location;
27 | private UnPeekLiveData moment;
28 | private UnPeekLiveData closeActivity;
29 |
30 | public ProtectedUnPeekLiveData getLocation() {
31 | if (location == null) location = new UnPeekLiveData<>();
32 | return location;
33 | }
34 |
35 | public ProtectedUnPeekLiveData getMoment() {
36 | if (moment == null) moment = new UnPeekLiveData<>();
37 | return moment;
38 | }
39 |
40 | public ProtectedUnPeekLiveData getCloseActivity() {
41 | if (closeActivity == null) closeActivity = new UnPeekLiveData<>();
42 | return closeActivity;
43 | }
44 |
45 | public void requestAddMoment(Moment moment) {
46 | this.moment.setValue(moment);
47 | }
48 |
49 | public void requestCloseActivity() {
50 | this.closeActivity.setValue(true);
51 | }
52 |
53 | public void requestAddLocation(String locationName) {
54 | this.location.setValue(locationName);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_one_more_thing/ui/OneMoreThingActivity.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_one_more_thing.ui;
4 |
5 | import android.os.Bundle;
6 |
7 | import androidx.databinding.DataBindingUtil;
8 |
9 | import com.kunminx.architecture.ui.BaseActivity;
10 | import com.kunminx.jetpack_java.R;
11 | import com.kunminx.jetpack_java.databinding.ActivityOneMoreThingBinding;
12 | import com.kunminx.jetpack_java.sample_one_more_thing.ui.state.OneMoreThingViewModel;
13 |
14 | /**
15 | * TODO:本示例专注于提供 Jetpack 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
16 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
17 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
18 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
19 | *
20 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
21 | *
22 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
23 | *
24 | *
25 | * Create by KunMinX at 19/10/16
26 | */
27 |
28 | public class OneMoreThingActivity extends BaseActivity {
29 |
30 | private OneMoreThingViewModel mOneMoreThingViewModel;
31 |
32 | @Override
33 | protected void onCreate(Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 |
36 | mOneMoreThingViewModel = getActivityScopeViewModel(OneMoreThingViewModel.class);
37 |
38 | ActivityOneMoreThingBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_one_more_thing);
39 | binding.setLifecycleOwner(this);
40 | binding.setVm(mOneMoreThingViewModel);
41 | binding.setClick(new ClickProxy());
42 | }
43 |
44 | public class ClickProxy {
45 | public void back() {
46 | finish();
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/java/com/kunminx/jetpack_java/sample_one_more_thing/ui/state/OneMoreThingViewModel.java:
--------------------------------------------------------------------------------
1 |
2 |
3 | package com.kunminx.jetpack_java.sample_one_more_thing.ui.state;
4 |
5 | import androidx.databinding.ObservableField;
6 | import androidx.lifecycle.ViewModel;
7 |
8 | /**
9 | * TODO:本示例专注于提供 Jetpack 组件的使用场景和示例,因而其他内容均保持 Android 引入 Jetpack 前的模样,
10 | * kotlin 模块提供同样的场景和基于 Kotlin 的写法,可对照查阅。
11 | * 并且本项目的示例从 sample_01 到 sample_05 是循序渐进地 Jetpack 化,
12 | * 如看完对 Jetpack 高频核心组件 "为什么要用"、"为什么要这样用" 有了一丝丝好奇心,可前往《Jetpack MVVM 精讲》和《Jetpack MVVM 最佳实践》项目查阅深度解析。
13 | *
14 | * https://juejin.im/post/5dafc49b6fb9a04e17209922
15 | *
16 | * https://github.com/KunMinX/Jetpack-MVVM-Best-Practice
17 | *
18 | *
19 | * Create by KunMinX at 2020/6/1
20 | */
21 | public class OneMoreThingViewModel extends ViewModel {
22 |
23 | public final ObservableField pageAssetPath = new ObservableField<>();
24 |
25 | {
26 | pageAssetPath.set("best_practice.html");
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/res/layout/activity_editor_livedata.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
18 |
19 |
33 |
34 |
45 |
46 |
60 |
61 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/res/layout/activity_list_viewmodel.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
18 |
19 |
27 |
28 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/res/layout/activity_location_databinding.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
10 |
11 |
14 |
15 |
18 |
19 |
20 |
23 |
24 |
35 |
36 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/res/layout/activity_location_lifecycles.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
17 |
18 |
26 |
27 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/res/layout/activity_main_navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/res/layout/activity_one_more_thing.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
11 |
12 |
15 |
16 |
17 |
18 |
21 |
22 |
33 |
34 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/res/layout/adapter_location.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
19 |
20 |
27 |
28 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/res/layout/adapter_location_databinding.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
11 |
12 |
13 |
18 |
19 |
29 |
30 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/res/layout/fragment_location_navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
10 |
11 |
14 |
15 |
18 |
19 |
20 |
24 |
25 |
36 |
37 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | One More Thing
7 | Jetpack MVVM 最佳实践
8 |
--------------------------------------------------------------------------------
/jetpack_java/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/jetpack_java/src/test/java/com/kunminx/jetpack_java/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.kunminx.jetpack_java;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/jetpack_kotlin/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/jetpack_kotlin/consumer-rules.pro
--------------------------------------------------------------------------------
/jetpack_kotlin/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/androidTest/java/com/flywith24/jetpack_kotlin/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4
4 | import androidx.test.platform.app.InstrumentationRegistry
5 | import org.junit.Assert.assertEquals
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | /**
10 | * Instrumented test, which will execute on an Android device.
11 | *
12 | * See [testing documentation](http://d.android.com/tools/testing).
13 | */
14 | @RunWith(AndroidJUnit4::class)
15 | class ExampleInstrumentedTest {
16 | @Test
17 | fun useAppContext() {
18 | // Context of the app under test.
19 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext
20 | assertEquals("com.flywith24.jetpack_kotlin.test", appContext.packageName)
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/common_data/APIs.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.common_data
2 |
3 | /**
4 | * @author Flywith24
5 | * @date 2020/5/30
6 | * time 12:22
7 | * description
8 | */
9 | object APIs {
10 | const val PIC_URL = "https://i.loli.net/2020/05/29/Dynh3KrQ7m8Oz4A.jpg"
11 | const val KUNMINX_URL = "https://upload.jianshu.io/users/upload_avatars/57036/3e7ae7bc-9b9b-46c8-8082-bb2481d979dc.jpg"
12 |
13 | const val FLYWITH24_URL = "https://upload-images.jianshu.io/upload_images/57036-48e9886afe74ea9b.jpeg"
14 |
15 | const val SCENE_URL = "https://upload-images.jianshu.io/upload_images/57036-99344035bfce65b8.jpeg"
16 |
17 | const val ADD_PIC_TIP_URL = "https://upload-images.jianshu.io/upload_images/57036-0c120ced543d506a.png"
18 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/common_data/Configs.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.common_data
2 |
3 | /**
4 | * @author Flywith24
5 | * @date 2020/5/30
6 | * time 12:16
7 | * description
8 | */
9 | object Configs {
10 | const val REQUEST_LOCATION_INFO = 0x00001
11 | const val REQUEST_NEW_MOMENT = 0x00002
12 | const val NEW_MOMENT = "NEW_MOMENT"
13 | const val LOCATION_RESULT = "LOCATION_RESULT"
14 | const val THIS_MOMENT = "THIS_MOMENT"
15 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/common_data/bean/LocationBean.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.common_data.bean
2 |
3 | /**
4 | * @author Flywith24
5 | * @date 2020/5/30
6 | * time 11:48
7 | * description
8 | */
9 | data class LocationBean(val locationName: String)
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/common_data/bean/Moment.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.common_data.bean
2 |
3 | import android.os.Parcelable
4 | import kotlinx.android.parcel.Parcelize
5 |
6 | /**
7 | * @author Flywith24
8 | * @date 2020/5/30
9 | * time 20:02
10 | * description
11 | */
12 | @Parcelize
13 | data class Moment(
14 | var uuid: String,
15 | val content: String?,
16 | val location: String?,
17 | val imgUrl: String,
18 | var username: String,
19 | var userAvatar: String
20 | ) : Parcelable
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/common_ui/adapter/DiffUtil.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.common_ui.adapter
2 |
3 | import androidx.recyclerview.widget.DiffUtil
4 | import com.flywith24.jetpack_kotlin.common_data.bean.LocationBean
5 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
6 |
7 | /**
8 | * @author Flywith24
9 | * @date 2020/5/31
10 | * time 23:00
11 | * description
12 | */
13 | object LocationDiffCallback : DiffUtil.ItemCallback() {
14 | override fun areItemsTheSame(oldItem: LocationBean, newItem: LocationBean): Boolean =
15 | oldItem == newItem
16 |
17 |
18 | override fun areContentsTheSame(oldItem: LocationBean, newItem: LocationBean): Boolean =
19 | oldItem.locationName == newItem.locationName
20 | }
21 |
22 | object MomentDiffCallback : DiffUtil.ItemCallback() {
23 | override fun areItemsTheSame(oldItem: Moment, newItem: Moment): Boolean {
24 | return oldItem.uuid == newItem.uuid
25 | }
26 |
27 | override fun areContentsTheSame(oldItem: Moment, newItem: Moment): Boolean {
28 | return oldItem.content == newItem.content &&
29 | oldItem.imgUrl == newItem.imgUrl &&
30 | oldItem.location == newItem.location &&
31 | oldItem.username == newItem.username &&
32 | oldItem.userAvatar == newItem.userAvatar
33 | }
34 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/common_ui/adapter/LocationAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.common_ui.adapter
2 |
3 | import android.view.LayoutInflater
4 | import android.view.View
5 | import android.view.ViewGroup
6 | import android.widget.TextView
7 | import androidx.recyclerview.widget.ListAdapter
8 | import androidx.recyclerview.widget.RecyclerView
9 | import com.flywith24.jetpack_kotlin.R
10 | import com.flywith24.jetpack_kotlin.common_data.bean.LocationBean
11 |
12 | /**
13 | * @author Flywith24
14 | * @date 2020/5/30
15 | * time 11:47
16 | * description
17 | * ListAdapter 强制使用 DiffUtil 比较数据变化,开发者无需手动调用各种 notify 方法亦可使用 recyclerView 的动画
18 | */
19 | class LocationAdapter(private val onClick: (LocationBean) -> Unit) :
20 | ListAdapter(LocationDiffCallback) {
21 |
22 | class ViewHolder(itemView: View, val onClick: (LocationBean) -> Unit) : RecyclerView.ViewHolder(itemView) {
23 | private var mTvTitle: TextView = itemView.findViewById(R.id.tv_title)
24 | private var currentLocation: LocationBean? = null
25 |
26 | init {
27 | itemView.setOnClickListener {
28 | currentLocation?.let {
29 | onClick(it)
30 | }
31 | }
32 | }
33 |
34 | fun bind(item: LocationBean) {
35 | currentLocation = item
36 | mTvTitle.text = item.locationName
37 | }
38 | }
39 |
40 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
41 | val view = LayoutInflater.from(parent.context).inflate(R.layout.kotlin_adapter_location, parent, false)
42 | return ViewHolder(view, onClick)
43 | }
44 |
45 | override fun onBindViewHolder(holder: ViewHolder, position: Int) {
46 | holder.bind(getItem(position))
47 | }
48 |
49 | override fun submitList(list: List?) {
50 | super.submitList(list) {
51 | submitList(if (list == null) emptyList() else ArrayList(list))
52 | }
53 | }
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_01_lifecycles/domain/LifecycleLocationManager.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_01_lifecycles.domain
2 |
3 | import androidx.lifecycle.DefaultLifecycleObserver
4 | import androidx.lifecycle.LifecycleOwner
5 | import com.flywith24.jetpack_kotlin.common_data.bean.LocationBean
6 | import java.util.*
7 | import kotlin.collections.ArrayList
8 | import kotlin.concurrent.timerTask
9 |
10 | /**
11 | * @author Flywith24
12 | * @date 2020/5/30
13 | * time 12:23
14 | * description
15 | */
16 | class LifecycleLocationManager private constructor() : DefaultLifecycleObserver {
17 | private var mTimer: Timer? = null
18 | private var mLocationBeans = ArrayList()
19 |
20 | private var mILocationCallback: ILocationCallback? = null
21 |
22 | fun setILocationCallback(callback: ((List) -> Unit)?) {
23 | mILocationCallback = object : ILocationCallback {
24 | override fun onListChanged(list: List) {
25 | callback?.invoke(list)
26 | }
27 | }
28 | }
29 |
30 | override fun onResume(owner: LifecycleOwner) {
31 | //TODO 我是获取附近位置列表信息的后台定位服务,我耗电巨大,我随着页面的 onResume 开启了
32 | mTimer = Timer()
33 | val task = timerTask {
34 | //模拟定位,假设开启了 GPS 并且每秒获取若干条新的位置信息
35 |
36 | mLocationBeans.add(LocationBean("台北夜市 ${System.currentTimeMillis()} 号"))
37 |
38 | mILocationCallback?.onListChanged(mLocationBeans)
39 | onResume(owner)
40 | }
41 |
42 | mTimer?.schedule(task, 250)
43 | }
44 |
45 | override fun onPause(owner: LifecycleOwner) {
46 | //TODO 我随着页面的 onPause 而关闭了
47 |
48 | mTimer?.cancel()
49 | mTimer = null
50 |
51 | mLocationBeans.clear()
52 | }
53 |
54 | companion object {
55 | private val sManager = LifecycleLocationManager()
56 | fun getInstance(): LifecycleLocationManager = sManager
57 | }
58 |
59 | interface ILocationCallback {
60 | fun onListChanged(list: List)
61 | }
62 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_01_lifecycles/ui/LifecycleEditorActivity.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_01_lifecycles.ui
2 |
3 | import android.content.Intent
4 | import android.os.Bundle
5 | import android.widget.ImageView
6 | import android.widget.TextView
7 | import androidx.activity.result.contract.ActivityResultContracts
8 | import androidx.appcompat.widget.Toolbar
9 | import com.flywith24.jetpack_kotlin.R
10 | import com.flywith24.jetpack_kotlin.common_data.APIs
11 | import com.flywith24.jetpack_kotlin.common_data.Configs
12 | import com.kunminx.architecture.ui.BaseActivity
13 | import com.kunminx.architecture.utils.loadImage
14 |
15 | /**
16 | * @author Flywith24
17 | * @date 2020/5/30
18 | * time 11:39
19 | * description
20 | */
21 | class LifecycleEditorActivity : BaseActivity(R.layout.kotlin_activity_lifecycles_detail) {
22 | /**
23 | * 不推荐使用 Kotlin Synthetics
24 | * 可以使用 ViewBinding 和 功能更强大的 DataBinding 来替换 findViewById
25 | *
26 | * 本示例尽量只演示单个组件的使用,因此没有使用 ViewBinding 或 DataBinding
27 | *
28 | * 详情参考 https://juejin.im/post/5e8ef0bc518825736b749705#heading-17
29 | */
30 | private lateinit var mTvLocation: TextView
31 | private lateinit var mImageView: ImageView
32 | private lateinit var mToolbar: Toolbar
33 |
34 | override fun onCreate(savedInstanceState: Bundle?) {
35 | super.onCreate(savedInstanceState)
36 |
37 | mTvLocation = findViewById(R.id.tv_locate)
38 | mImageView = findViewById(R.id.iv)
39 | mToolbar = findViewById(R.id.toolbar)
40 | mToolbar.apply {
41 | setNavigationOnClickListener { finish() }
42 | inflateMenu(R.menu.editor_menu)
43 | setOnMenuItemClickListener { item ->
44 | if (item.itemId == R.id.menu_save) {
45 | showLongToast(getString(R.string.lifecycle_save_tip))
46 | }
47 | return@setOnMenuItemClickListener true
48 | }
49 | }
50 |
51 | mImageView.loadImage(APIs.SCENE_URL)
52 |
53 | mTvLocation.setOnClickListener {
54 | /**
55 | * startActivityForResult API 已弃用,可以使用新的 ActivityResult API
56 | * 详情见 https://github.com/Flywith24/Flywith24-ActivityResultRequest
57 | */
58 | registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
59 | val location = it.data?.getStringExtra(Configs.LOCATION_RESULT)
60 | mTvLocation.text = location
61 | }.launch(Intent(this, LifecycleLocationActivity::class.java))
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_01_lifecycles/ui/LifecycleLocationActivity.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_01_lifecycles.ui
2 |
3 | import android.app.Activity
4 | import android.content.Intent
5 | import android.os.Bundle
6 | import androidx.appcompat.widget.Toolbar
7 | import androidx.recyclerview.widget.RecyclerView
8 | import com.flywith24.jetpack_kotlin.R
9 | import com.flywith24.jetpack_kotlin.common_data.Configs
10 | import com.flywith24.jetpack_kotlin.common_data.bean.LocationBean
11 | import com.flywith24.jetpack_kotlin.common_ui.adapter.LocationAdapter
12 | import com.flywith24.jetpack_kotlin.sample_01_lifecycles.domain.LifecycleLocationManager
13 | import com.kunminx.architecture.ui.BaseActivity
14 |
15 | /**
16 | * @author Flywith24
17 | * @date 2020/5/30
18 | * time 11:20
19 | * description
20 | */
21 | class LifecycleLocationActivity : BaseActivity(R.layout.kotlin_activity_lifecycles_location) {
22 | /**
23 | * 不推荐使用 Kotlin Synthetics
24 | * 可以使用 ViewBinding 和 功能更强大的 DataBinding 来替换 findViewById
25 | *
26 | * 本示例尽量只演示单个组件的使用,因此没有使用 ViewBinding 或 DataBinding
27 | *
28 | * 详情参考 https://juejin.im/post/5e8ef0bc518825736b749705#heading-17
29 | */
30 | private lateinit var mRecyclerView: RecyclerView
31 | private lateinit var mToolbar: Toolbar
32 |
33 | private val mAdapter by lazy { LocationAdapter { adapterClick(it) } }
34 |
35 | private fun adapterClick(locationBean: LocationBean) {
36 | setResult(Activity.RESULT_OK, Intent().putExtra(Configs.LOCATION_RESULT, locationBean.locationName))
37 | finish()
38 | }
39 |
40 | override fun onCreate(savedInstanceState: Bundle?) {
41 | super.onCreate(savedInstanceState)
42 |
43 | mToolbar = findViewById(R.id.toolbar)
44 | mToolbar.setNavigationOnClickListener { finish() }
45 |
46 | mRecyclerView = findViewById(R.id.rv)
47 | mRecyclerView.adapter = mAdapter
48 |
49 | lifecycle.addObserver(LifecycleLocationManager.getInstance())
50 |
51 | LifecycleLocationManager.getInstance().setILocationCallback { list ->
52 | runOnUiThread {
53 | mAdapter.submitList(list)
54 | }
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_02_livedata/domain/LiveDataLocationManager.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_02_livedata.domain
2 |
3 | import androidx.lifecycle.DefaultLifecycleObserver
4 | import androidx.lifecycle.LifecycleOwner
5 | import androidx.lifecycle.LiveData
6 | import androidx.lifecycle.MutableLiveData
7 | import com.flywith24.jetpack_kotlin.common_data.bean.LocationBean
8 | import java.util.*
9 | import kotlin.collections.ArrayList
10 | import kotlin.concurrent.timerTask
11 |
12 | /**
13 | * @author Flywith24
14 | * @date 2020/5/30
15 | * time 12:23
16 | * description
17 | */
18 | class LiveDataLocationManager private constructor() : DefaultLifecycleObserver {
19 | private var mTimer: Timer? = null
20 | private val mLocationBeans = MutableLiveData>()
21 |
22 | fun getLocationBeans(): LiveData> = mLocationBeans
23 |
24 | private val mList = ArrayList()
25 |
26 | override fun onResume(owner: LifecycleOwner) {
27 | //TODO 我是获取附近位置列表信息的后台定位服务,我耗电巨大,我随着页面的 onResume 开启了
28 |
29 | mTimer = Timer()
30 |
31 | val task = timerTask {
32 | //模拟定位,假设开启了 GPS 并且每秒获取若干条新的位置信息
33 |
34 | mList.add(LocationBean("台北夜市 ${System.currentTimeMillis()} 号"))
35 | mLocationBeans.postValue(mList)
36 | onResume(owner)
37 | }
38 |
39 | mTimer?.schedule(task, 250)
40 | }
41 |
42 | override fun onPause(owner: LifecycleOwner) {
43 | //TODO 我随着页面的 onPause 而关闭了
44 |
45 | mTimer?.cancel()
46 | mTimer = null
47 |
48 | mList.clear()
49 | }
50 |
51 | companion object {
52 | private val sManager = LiveDataLocationManager()
53 | fun getInstance(): LiveDataLocationManager = sManager
54 | }
55 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_02_livedata/ui/LiveDataEditorActivity.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_02_livedata.ui
2 |
3 | import android.content.Intent
4 | import android.os.Bundle
5 | import android.widget.ImageView
6 | import android.widget.TextView
7 | import androidx.activity.result.contract.ActivityResultContracts
8 | import androidx.appcompat.widget.Toolbar
9 | import com.flywith24.jetpack_kotlin.R
10 | import com.flywith24.jetpack_kotlin.common_data.APIs
11 | import com.flywith24.jetpack_kotlin.common_data.Configs
12 | import com.kunminx.architecture.ui.BaseActivity
13 | import com.kunminx.architecture.utils.loadImage
14 |
15 | /**
16 | * @author Flywith24
17 | * @date 2020/5/30
18 | * time 20:31
19 | * description
20 | */
21 | class LiveDataEditorActivity : BaseActivity(R.layout.kotlin_activity_livedata_editor) {
22 | /**
23 | * 不推荐使用 Kotlin Synthetics
24 | * 可以使用 ViewBinding 和 功能更强大的 DataBinding 来替换 findViewById
25 | *
26 | * 本示例尽量只演示单个组件的使用,因此没有使用 ViewBinding 或 DataBinding
27 | *
28 | * 详情参考 https://juejin.im/post/5e8ef0bc518825736b749705#heading-17
29 | */
30 | private lateinit var mImageView: ImageView
31 | private lateinit var mTvLocation: TextView
32 | private lateinit var mToolbar: Toolbar
33 |
34 | override fun onCreate(savedInstanceState: Bundle?) {
35 | super.onCreate(savedInstanceState)
36 | mImageView = findViewById(R.id.iv)
37 | mTvLocation = findViewById(R.id.tv_locate)
38 |
39 | mToolbar = findViewById(R.id.toolbar)
40 | mToolbar.apply {
41 | setNavigationOnClickListener { finish() }
42 | inflateMenu(R.menu.editor_menu)
43 | setOnMenuItemClickListener { item ->
44 | if (item.itemId == R.id.menu_save) {
45 | showLongToast(getString(R.string.liveData_save_tip))
46 | }
47 | return@setOnMenuItemClickListener true
48 | }
49 | }
50 |
51 | mImageView.loadImage(APIs.SCENE_URL)
52 |
53 | mTvLocation.setOnClickListener {
54 |
55 | /**
56 | * startActivityForResult API 已弃用,可以使用新的 ActivityResult API
57 | * 详情见 https://github.com/Flywith24/Flywith24-ActivityResultRequest
58 | */
59 | registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
60 | val location = it.data?.getStringExtra(Configs.LOCATION_RESULT)
61 | mTvLocation.text = location
62 | }.launch(Intent(this, LiveDataLocationActivity::class.java))
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_02_livedata/ui/LiveDataLocationActivity.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_02_livedata.ui
2 |
3 | import android.app.Activity
4 | import android.content.Intent
5 | import android.os.Bundle
6 | import androidx.appcompat.widget.Toolbar
7 |
8 | import androidx.recyclerview.widget.RecyclerView
9 | import com.flywith24.jetpack_kotlin.R
10 | import com.flywith24.jetpack_kotlin.common_data.Configs
11 | import com.flywith24.jetpack_kotlin.common_data.bean.LocationBean
12 | import com.flywith24.jetpack_kotlin.common_ui.adapter.LocationAdapter
13 | import com.flywith24.jetpack_kotlin.sample_02_livedata.domain.LiveDataLocationManager
14 | import com.kunminx.architecture.ui.BaseActivity
15 |
16 | /**
17 | * @author Flywith24
18 | * @date 2020/5/30
19 | * time 20:31
20 | * description
21 | */
22 | class LiveDataLocationActivity : BaseActivity(R.layout.kotlin_activity_livedata_list) {
23 | /**
24 | * 不推荐使用 Kotlin Synthetics
25 | * 可以使用 ViewBinding 和 功能更强大的 DataBinding 来替换 findViewById
26 | *
27 | * 本示例尽量只演示单个组件的使用,因此没有使用 ViewBinding 或 DataBinding
28 | *
29 | * 详情参考 https://juejin.im/post/5e8ef0bc518825736b749705#heading-17
30 | */
31 | private lateinit var mRecyclerView: RecyclerView
32 | private lateinit var mToolbar: Toolbar
33 |
34 | private val mAdapter: LocationAdapter by lazy { LocationAdapter { adapterClick(it) } }
35 |
36 | private fun adapterClick(locationBean: LocationBean) {
37 | setResult(Activity.RESULT_OK, Intent().putExtra(Configs.LOCATION_RESULT, locationBean.locationName))
38 | finish()
39 | }
40 |
41 | override fun onCreate(savedInstanceState: Bundle?) {
42 | super.onCreate(savedInstanceState)
43 |
44 | mToolbar = findViewById(R.id.toolbar)
45 | mToolbar.setNavigationOnClickListener { finish() }
46 |
47 | mRecyclerView = findViewById(R.id.rv)
48 | mRecyclerView.adapter = mAdapter
49 |
50 | lifecycle.addObserver(LiveDataLocationManager.getInstance())
51 |
52 | LiveDataLocationManager.getInstance().getLocationBeans().observe(this) { list ->
53 | mAdapter.submitList(list)
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_03_viewmodel/data/DataRepository.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_03_viewmodel.data
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import com.flywith24.jetpack_kotlin.common_data.APIs
5 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
6 | import java.util.*
7 |
8 | /**
9 | * @author Flywith24
10 | * @date 2020/5/31
11 | * time 22:03
12 | * description
13 | */
14 | internal class DataRepository private constructor() {
15 |
16 | fun requestList(liveData: MutableLiveData>) {
17 | val list = listOf(
18 | Moment(getUUID(), "刚刚在掘金发表了最新一期动态,感兴趣的小伙伴可前往查阅",
19 | "重庆朝天门码头", APIs.SCENE_URL, "KunMinX", APIs.KUNMINX_URL),
20 | Moment(getUUID(), "刚刚在掘金发表了最新一期动态,感兴趣的小伙伴可前往查阅",
21 | "重庆朝天门码头", APIs.SCENE_URL, "Flywith24", APIs.FLYWITH24_URL),
22 | Moment(getUUID(), "刚刚在掘金发表了最新一期动态,感兴趣的小伙伴可前往查阅",
23 | "重庆朝天门码头", APIs.SCENE_URL, "KunMinX", APIs.KUNMINX_URL),
24 | Moment(getUUID(), "刚刚在掘金发表了最新一期动态,感兴趣的小伙伴可前往查阅",
25 | "重庆朝天门码头", APIs.SCENE_URL, "Flywith24", APIs.FLYWITH24_URL),
26 | Moment(getUUID(), "刚刚在掘金发表了最新一期动态,感兴趣的小伙伴可前往查阅",
27 | "重庆朝天门码头", APIs.SCENE_URL, "KunMinX", APIs.KUNMINX_URL),
28 | Moment(getUUID(), "刚刚在掘金发表了最新一期动态,感兴趣的小伙伴可前往查阅",
29 | "重庆朝天门码头", APIs.SCENE_URL, "Flywith24", APIs.FLYWITH24_URL),
30 | Moment(getUUID(), "刚刚在掘金发表了最新一期动态,感兴趣的小伙伴可前往查阅",
31 | "重庆朝天门码头", APIs.SCENE_URL, "KunMinX", APIs.KUNMINX_URL),
32 | Moment(getUUID(), "刚刚在掘金发表了最新一期动态,感兴趣的小伙伴可前往查阅",
33 | "重庆朝天门码头", APIs.SCENE_URL, "Flywith24", APIs.FLYWITH24_URL)
34 |
35 | )
36 |
37 | liveData.value = list
38 |
39 | }
40 |
41 | private fun getUUID(): String = UUID.randomUUID().toString().replace("-", "")
42 |
43 | companion object {
44 | private val sRepository = DataRepository()
45 | fun getInstance(): DataRepository = sRepository
46 | }
47 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_03_viewmodel/domain/MomentRequest.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_03_viewmodel.domain
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.MutableLiveData
5 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
6 | import com.flywith24.jetpack_kotlin.sample_03_viewmodel.data.DataRepository
7 |
8 | /**
9 | * @author Flywith24
10 | * @date 2020/5/31
11 | * time 22:09
12 | * description
13 | */
14 | internal class MomentRequest : Request.IMomentRequest {
15 | private val mListMutableLiveData = MutableLiveData>()
16 |
17 | override fun getListMutableLiveData(): LiveData> = mListMutableLiveData
18 |
19 | override fun requestList() {
20 | DataRepository.getInstance().requestList(mListMutableLiveData)
21 | }
22 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_03_viewmodel/domain/Request.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_03_viewmodel.domain
2 |
3 | import androidx.lifecycle.LiveData
4 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
5 |
6 | /**
7 | * @author Flywith24
8 | * @date 2020/5/31
9 | * time 22:10
10 | * description
11 | */
12 | internal class Request {
13 | interface IMomentRequest {
14 |
15 | fun getListMutableLiveData(): LiveData>
16 |
17 | fun requestList()
18 | }
19 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_03_viewmodel/ui/ViewModelListActivity.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_03_viewmodel.ui
2 |
3 | import android.os.Bundle
4 | import androidx.activity.viewModels
5 | import androidx.appcompat.widget.Toolbar
6 | import androidx.recyclerview.widget.RecyclerView
7 | import com.flywith24.jetpack_kotlin.R
8 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
9 | import com.flywith24.jetpack_kotlin.common_ui.adapter.MomentAdapter
10 | import com.flywith24.jetpack_kotlin.sample_03_viewmodel.ui.state.ListViewModel
11 | import com.kunminx.architecture.ui.BaseActivity
12 |
13 | /**
14 | * @author Flywith24
15 | * @date 2020/5/31
16 | * time 22:02
17 | * description
18 | */
19 | class ViewModelListActivity : BaseActivity(R.layout.kotlin_activity_list_viewmodel) {
20 |
21 | /**
22 | * activity 级别共享 ViewModel
23 | *
24 | * activity-ktx 扩展函数
25 | *
26 | * ViewModel 如何控制作用域,请参考
27 | * https://juejin.im/post/5e786d415188255e00661a4e#heading-10
28 | */
29 | private val mListViewModel by viewModels()
30 |
31 | /**
32 | * 不推荐使用 Kotlin Synthetics
33 | * 可以使用 ViewBinding 和 功能更强大的 DataBinding 来替换 findViewById
34 | *
35 | * 本示例尽量只演示单个组件的使用,因此没有使用 ViewBinding 或 DataBinding
36 | *
37 | * 详情参考 https://juejin.im/post/5e8ef0bc518825736b749705#heading-17
38 | */
39 | private lateinit var mRecyclerView: RecyclerView
40 | private lateinit var mToolbar: Toolbar
41 |
42 | private val mAdapter by lazy { MomentAdapter { adapterClick(it) } }
43 |
44 | private fun adapterClick(moment: Moment) {
45 | showLongToast(getString(R.string.viewmodel_item_click_tip))
46 | }
47 |
48 | override fun onCreate(savedInstanceState: Bundle?) {
49 | super.onCreate(savedInstanceState)
50 | mToolbar = findViewById(R.id.toolbar)
51 | mToolbar.setNavigationOnClickListener { finish() }
52 |
53 | mRecyclerView = findViewById(R.id.rv)
54 |
55 | mRecyclerView.adapter = mAdapter
56 |
57 | mListViewModel.getListMutableLiveData().observe(this) { list ->
58 | mAdapter.submitList(list)
59 | }
60 |
61 | mListViewModel.requestList()
62 | }
63 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_03_viewmodel/ui/state/ListViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_03_viewmodel.ui.state
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.ViewModel
5 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
6 | import com.flywith24.jetpack_kotlin.sample_03_viewmodel.domain.MomentRequest
7 | import com.flywith24.jetpack_kotlin.sample_03_viewmodel.domain.Request
8 |
9 | /**
10 | * @author Flywith24
11 | * @date 2020/5/31
12 | * time 22:03
13 | * description
14 | */
15 | internal class ListViewModel : ViewModel(), Request.IMomentRequest {
16 |
17 | private val mMomentRequest by lazy { MomentRequest() }
18 |
19 | override fun getListMutableLiveData(): LiveData> = mMomentRequest.getListMutableLiveData()
20 |
21 | override fun requestList() {
22 | mMomentRequest.requestList()
23 | }
24 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_04_databinding/ui/DataBindingDetailActivity.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_04_databinding.ui
2 |
3 | import android.os.Bundle
4 | import androidx.activity.viewModels
5 | import androidx.databinding.DataBindingUtil
6 | import com.flywith24.jetpack_kotlin.R
7 | import com.flywith24.jetpack_kotlin.common_data.Configs
8 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
9 | import com.flywith24.jetpack_kotlin.databinding.KotlinActivityDetailDatabindingBinding
10 | import com.flywith24.jetpack_kotlin.sample_04_databinding.ui.state.DetailViewModel
11 | import com.kunminx.architecture.ui.BaseActivity
12 |
13 | /**
14 | * @author Flywith24
15 | * @date 2020/5/31
16 | * time 23:30
17 | * description
18 | */
19 | class DataBindingDetailActivity : BaseActivity() {
20 |
21 | /**
22 | * activity 级别共享 ViewModel
23 | *
24 | * activity-ktx 扩展函数
25 | *
26 | * ViewModel 如何控制作用域,请参考
27 | * https://juejin.im/post/5e786d415188255e00661a4e#heading-10
28 | */
29 | private val mDetailViewModel by viewModels()
30 |
31 | override fun onCreate(savedInstanceState: Bundle?) {
32 | super.onCreate(savedInstanceState)
33 |
34 | val binding = DataBindingUtil.setContentView(this, R.layout.kotlin_activity_detail_databinding)
35 | binding.lifecycleOwner = this
36 | binding.vm = mDetailViewModel
37 | binding.click = ClickProxy()
38 |
39 | val moment = intent.getParcelableExtra(Configs.THIS_MOMENT)
40 | moment?.let {
41 | mDetailViewModel.initState(it)
42 | }
43 | }
44 |
45 | inner class ClickProxy {
46 | fun back() {
47 | finish()
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_04_databinding/ui/DataBindingLocationActivity.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_04_databinding.ui
2 |
3 | import android.app.Activity
4 | import android.content.Intent
5 | import android.os.Bundle
6 | import androidx.activity.viewModels
7 | import androidx.databinding.DataBindingUtil
8 |
9 | import com.flywith24.jetpack_kotlin.R
10 | import com.flywith24.jetpack_kotlin.common_data.Configs
11 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
12 | import com.flywith24.jetpack_kotlin.databinding.KotlinActivityLocationDatabindingBinding
13 | import com.flywith24.jetpack_kotlin.sample_02_livedata.domain.LiveDataLocationManager
14 | import com.flywith24.jetpack_kotlin.sample_04_databinding.ui.adapter.DataBindingLocationAdapter
15 | import com.flywith24.jetpack_kotlin.sample_04_databinding.ui.state.LocationViewModel
16 | import com.kunminx.architecture.ui.BaseActivity
17 |
18 | /**
19 | * @author Flywith24
20 | * @date 2020/5/31
21 | * time 23:14
22 | * description
23 | */
24 | class DataBindingLocationActivity : BaseActivity() {
25 | /**
26 | * activity 级别共享 ViewModel
27 | *
28 | * activity-ktx 扩展函数
29 | *
30 | * ViewModel 如何控制作用域,请参考
31 | * https://juejin.im/post/5e786d415188255e00661a4e#heading-10
32 | */
33 | private val mLocationViewModel by viewModels()
34 |
35 | override fun onCreate(savedInstanceState: Bundle?) {
36 | super.onCreate(savedInstanceState)
37 |
38 | val binding = DataBindingUtil.setContentView(this, R.layout.kotlin_activity_location_databinding)
39 | binding.lifecycleOwner = this
40 | binding.vm = mLocationViewModel
41 | binding.click = ClickProxy()
42 | binding.adapter = DataBindingLocationAdapter(applicationContext).apply {
43 | setOnItemClickListener { item, _ ->
44 | setResult(Activity.RESULT_OK,
45 | Intent().putExtra(Configs.LOCATION_RESULT, item.locationName))
46 | finish()
47 | }
48 | }
49 |
50 | lifecycle.addObserver(LiveDataLocationManager.getInstance())
51 |
52 | LiveDataLocationManager.getInstance().getLocationBeans().observe(this) { list ->
53 | mLocationViewModel.list.value = list
54 | }
55 | }
56 |
57 | inner class ClickProxy {
58 | fun back() {
59 | finish()
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_04_databinding/ui/adapter/DataBindingLocationAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_04_databinding.ui.adapter
2 |
3 | import android.content.Context
4 | import androidx.recyclerview.widget.RecyclerView
5 | import com.flywith24.jetpack_kotlin.R
6 | import com.flywith24.jetpack_kotlin.common_data.bean.LocationBean
7 | import com.flywith24.jetpack_kotlin.common_ui.adapter.LocationDiffCallback
8 | import com.flywith24.jetpack_kotlin.databinding.KotlinAdapterLocationDatabindingBinding
9 | import com.kunminx.architecture.ui.adapter.SimpleBindingAdapter
10 |
11 | /**
12 | * @author Flywith24
13 | * @date 2020/5/31
14 | * time 22:56
15 | * description
16 | */
17 | class DataBindingLocationAdapter(context: Context) : SimpleBindingAdapter(context, R.layout.kotlin_adapter_location_databinding, LocationDiffCallback) {
18 | override fun onBindItem(binding: KotlinAdapterLocationDatabindingBinding?, item: LocationBean?, holder: RecyclerView.ViewHolder?) {
19 | binding?.bean = item
20 | }
21 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_04_databinding/ui/adapter/DataBindingMomentAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_04_databinding.ui.adapter
2 |
3 | import android.content.Context
4 | import androidx.recyclerview.widget.RecyclerView
5 | import com.flywith24.jetpack_kotlin.R
6 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
7 | import com.flywith24.jetpack_kotlin.common_ui.adapter.MomentDiffCallback
8 | import com.flywith24.jetpack_kotlin.databinding.KotlinAdapterMomentDatabindingBinding
9 | import com.kunminx.architecture.ui.adapter.SimpleBindingAdapter
10 |
11 | /**
12 | * @author Flywith24
13 | * @date 2020/5/31
14 | * time 22:56
15 | * description
16 | */
17 | class DataBindingMomentAdapter(context: Context) : SimpleBindingAdapter(context, R.layout.kotlin_adapter_moment_databinding, MomentDiffCallback) {
18 | override fun onBindItem(binding: KotlinAdapterMomentDatabindingBinding?, item: Moment?, holder: RecyclerView.ViewHolder?) {
19 | binding?.moment = item
20 | }
21 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_04_databinding/ui/state/DetailViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_04_databinding.ui.state
2 |
3 | import androidx.databinding.ObservableField
4 | import androidx.lifecycle.ViewModel
5 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
6 |
7 | /**
8 | * @author Flywith24
9 | * @date 2020/5/31
10 | * time 23:11
11 | * description
12 | */
13 | class DetailViewModel : ViewModel() {
14 | val imgUrl = ObservableField()
15 | val name = ObservableField()
16 | val content = ObservableField()
17 | val location = ObservableField()
18 | val avatar = ObservableField()
19 |
20 | fun initState(moment: Moment) {
21 | avatar.set(moment.userAvatar)
22 | name.set(moment.username)
23 | content.set(moment.content)
24 | imgUrl.set(moment.imgUrl)
25 | location.set(moment.location)
26 | }
27 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_04_databinding/ui/state/EditorViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_04_databinding.ui.state
2 |
3 | import androidx.databinding.ObservableField
4 | import androidx.lifecycle.ViewModel
5 | import com.flywith24.jetpack_kotlin.common_data.APIs
6 |
7 | /**
8 | * @author Flywith24
9 | * @date 2020/5/31
10 | * time 23:11
11 | * description
12 | */
13 | class EditorViewModel : ViewModel() {
14 | val imgUrl = ObservableField(APIs.ADD_PIC_TIP_URL)
15 | val content = ObservableField("")
16 | val location = ObservableField("点击添加定位")
17 |
18 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_04_databinding/ui/state/ListViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_04_databinding.ui.state
2 |
3 | import androidx.lifecycle.LiveData
4 | import androidx.lifecycle.MutableLiveData
5 | import androidx.lifecycle.ViewModel
6 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
7 | import com.flywith24.jetpack_kotlin.sample_03_viewmodel.domain.MomentRequest
8 | import com.flywith24.jetpack_kotlin.sample_03_viewmodel.domain.Request
9 |
10 | /**
11 | * @author Flywith24
12 | * @date 2020/5/31
13 | * time 22:03
14 | * description
15 | */
16 | internal class ListViewModel : ViewModel(), Request.IMomentRequest {
17 |
18 | val list = MutableLiveData>(emptyList())
19 | val autoScrollToTopWhenInsert = MutableLiveData(true)
20 |
21 | private val mMomentRequest by lazy { MomentRequest() }
22 |
23 | override fun getListMutableLiveData(): LiveData> = mMomentRequest.getListMutableLiveData()
24 |
25 | override fun requestList() {
26 | mMomentRequest.requestList()
27 | }
28 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_04_databinding/ui/state/LocationViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_04_databinding.ui.state
2 |
3 | import androidx.lifecycle.MutableLiveData
4 | import androidx.lifecycle.ViewModel
5 | import com.flywith24.jetpack_kotlin.common_data.bean.LocationBean
6 |
7 | /**
8 | * @author Flywith24
9 | * @date 2020/5/31
10 | * time 23:13
11 | * description
12 | */
13 | class LocationViewModel : ViewModel() {
14 | val list = MutableLiveData>()
15 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_05_navigation/ui/NavigationDetailFragment.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_05_navigation.ui
2 |
3 | import android.os.Bundle
4 | import android.view.LayoutInflater
5 | import android.view.View
6 | import android.view.ViewGroup
7 | import androidx.fragment.app.viewModels
8 | import com.flywith24.jetpack_kotlin.R
9 | import com.flywith24.jetpack_kotlin.common_data.Configs
10 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
11 | import com.flywith24.jetpack_kotlin.databinding.KotlinFragmentDetailNavigationBinding
12 | import com.flywith24.jetpack_kotlin.sample_04_databinding.ui.state.DetailViewModel
13 | import com.kunminx.architecture.ui.BaseFragment
14 |
15 | /**
16 | * @author Flywith24
17 | * @date 2020/6/1
18 | * time 22:06
19 | * description
20 | */
21 | class NavigationDetailFragment : BaseFragment() {
22 | /**
23 | * fragment-ktx 扩展函数
24 | */
25 | private val mDetailViewModel by viewModels()
26 |
27 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
28 | val view = inflater.inflate(R.layout.kotlin_fragment_detail_navigation, container, false)
29 | val binding = KotlinFragmentDetailNavigationBinding.bind(view)
30 | binding.lifecycleOwner = viewLifecycleOwner
31 | binding.vm = mDetailViewModel
32 | binding.click = ClickProxy()
33 | return view
34 | }
35 |
36 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
37 | super.onViewCreated(view, savedInstanceState)
38 |
39 | val moment = arguments?.getParcelable(Configs.THIS_MOMENT)
40 | moment?.let {
41 | mDetailViewModel.initState(it)
42 | }
43 | }
44 |
45 | inner class ClickProxy {
46 | fun back() {
47 | nav().navigateUp()
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_05_navigation/ui/NavigationMainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_05_navigation.ui
2 |
3 | import android.os.Bundle
4 | import androidx.activity.viewModels
5 | import com.flywith24.jetpack_kotlin.R
6 | import com.flywith24.jetpack_kotlin.sample_05_navigation.ui.callback.SharedViewModel
7 | import com.kunminx.architecture.kotlin.observeEvent
8 | import com.kunminx.architecture.ui.BaseActivity
9 |
10 | /**
11 | * @author Flywith24
12 | * @date 2020/6/1
13 | * time 21:56
14 | * description
15 | */
16 | class NavigationMainActivity : BaseActivity(R.layout.kotlin_activity_main_navigation) {
17 | private val mSharedViewModel by viewModels()
18 |
19 | override fun onCreate(savedInstanceState: Bundle?) {
20 | super.onCreate(savedInstanceState)
21 | mSharedViewModel.closeActivity.observeEvent(this) {
22 | finish()
23 | }
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_05_navigation/ui/callback/SharedViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_05_navigation.ui.callback
2 |
3 | import androidx.lifecycle.ViewModel
4 | import com.flywith24.jetpack_kotlin.common_data.bean.Moment
5 | import com.kunminx.architecture.kotlin.EventMutableLiveData
6 |
7 | /**
8 | * @author Flywith24
9 | * @date 2020/6/1
10 | * time 21:54
11 | * description
12 | */
13 | class SharedViewModel : ViewModel() {
14 | /**
15 | * 使用 包装类 解决 LiveData 粘性事件的问题
16 | * 详见
17 | * https://juejin.im/post/5ed9c92ce51d45789b35afa9 (kotlin 扩展函数和 typealias 封装 LiveData)
18 | *
19 | * https://juejin.im/post/5b2b1b2cf265da5952314b63 (粘性事件)
20 | */
21 | val location = EventMutableLiveData()
22 | val moment = EventMutableLiveData()
23 | val closeActivity = EventMutableLiveData()
24 |
25 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_one_more_thing/ui/OneMoreThingActivity.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_one_more_thing.ui
2 |
3 | import android.os.Bundle
4 | import androidx.activity.viewModels
5 | import androidx.databinding.DataBindingUtil
6 | import com.flywith24.jetpack_kotlin.R
7 | import com.flywith24.jetpack_kotlin.databinding.KotlinActivityOneMoreThingBinding
8 | import com.flywith24.jetpack_kotlin.sample_one_more_thing.ui.state.OneMoreThingViewModel
9 | import com.kunminx.architecture.ui.BaseActivity
10 |
11 | /**
12 | * @author Flywith24
13 | * @date 2020/6/10
14 | * time 00:31
15 | * description
16 | */
17 | class OneMoreThingActivity : BaseActivity() {
18 |
19 | /**
20 | * activity 级别共享 ViewModel
21 | *
22 | * activity-ktx 扩展函数
23 | *
24 | * ViewModel 如何控制作用域,请参考
25 | * https://juejin.im/post/5e786d415188255e00661a4e#heading-10
26 | */
27 | private val mOneMoreThingViewModel by viewModels()
28 |
29 | override fun onCreate(savedInstanceState: Bundle?) {
30 | super.onCreate(savedInstanceState)
31 |
32 | with(DataBindingUtil.setContentView(this, R.layout.kotlin_activity_one_more_thing)) {
33 | lifecycleOwner = this@OneMoreThingActivity
34 | vm = mOneMoreThingViewModel
35 | click = ClickProxy()
36 | }
37 | }
38 |
39 | inner class ClickProxy {
40 | fun back() {
41 | finish()
42 | }
43 | }
44 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/java/com/flywith24/jetpack_kotlin/sample_one_more_thing/ui/state/OneMoreThingViewModel.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin.sample_one_more_thing.ui.state
2 |
3 | import androidx.databinding.ObservableField
4 | import androidx.lifecycle.ViewModel
5 |
6 | /**
7 | * @author Flywith24
8 | * @date 2020/6/10
9 | * time 00:35
10 | * description
11 | */
12 | class OneMoreThingViewModel : ViewModel() {
13 | val pageAssetPath = ObservableField("use_jetpack.html")
14 | }
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_activity_editor_livedata.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
17 |
18 |
31 |
32 |
42 |
43 |
57 |
58 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_activity_lifecycles_detail.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
17 |
18 |
31 |
32 |
42 |
43 |
57 |
58 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_activity_lifecycles_location.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
17 |
18 |
27 |
28 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_activity_list_viewmodel.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
18 |
19 |
28 |
29 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_activity_livedata_editor.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
17 |
18 |
31 |
32 |
42 |
43 |
57 |
58 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_activity_livedata_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
18 |
19 |
28 |
29 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_activity_location_databinding.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
6 |
7 |
8 |
9 |
12 |
13 |
16 |
17 |
20 |
21 |
22 |
23 |
26 |
27 |
38 |
39 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_activity_main_navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_activity_one_more_thing.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
10 |
11 |
14 |
15 |
16 |
17 |
20 |
21 |
32 |
33 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_adapter_location.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
17 |
18 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_adapter_location_databinding.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 |
15 |
16 |
24 |
25 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/layout/kotlin_fragment_location_navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
10 |
11 |
14 |
15 |
18 |
19 |
20 |
23 |
24 |
35 |
36 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/navigation/kotlin_nav_graph.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
12 |
15 |
18 |
19 |
20 |
24 |
27 |
28 |
29 |
30 |
34 |
35 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/jetpack_kotlin/src/test/java/com/flywith24/jetpack_kotlin/ExampleUnitTest.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.jetpack_kotlin
2 |
3 | import org.junit.Assert.assertEquals
4 | import org.junit.Test
5 |
6 | /**
7 | * Example local unit test, which will execute on the development machine (host).
8 | *
9 | * See [testing documentation](http://d.android.com/tools/testing).
10 | */
11 | class ExampleUnitTest {
12 | @Test
13 | fun addition_isCorrect() {
14 | assertEquals(4, 2 + 2)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':common_res'
2 | includeBuild('version_config')
3 | include ':app', ':architecture'
4 | rootProject.name = 'PureMusic'
5 | include ':jetpack_java'
6 | include ':jetpack_kotlin'
7 |
--------------------------------------------------------------------------------
/version_config/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/version_config/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | jcenter()
4 | google()
5 | }
6 | dependencies {
7 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.0"
8 | }
9 | }
10 |
11 | apply plugin: 'kotlin'
12 | apply plugin: 'java-gradle-plugin'
13 |
14 | repositories {
15 | jcenter()
16 | google()
17 | }
18 |
19 | dependencies {
20 | implementation gradleApi()
21 | implementation "org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.0"
22 | }
23 |
24 | compileTestKotlin {
25 | kotlinOptions {
26 | jvmTarget = "1.8"
27 | }
28 | }
29 |
30 | gradlePlugin {
31 | plugins {
32 | version {
33 | id = 'com.flywith24.version'
34 | implementationClass = 'com.flywith24.version_config.VersionConfigPlugin'
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/version_config/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/version_config/consumer-rules.pro
--------------------------------------------------------------------------------
/version_config/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Jul 22 08:52:21 CST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
7 |
--------------------------------------------------------------------------------
/version_config/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/version_config/settings.gradle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Jetpack-Missionary/Jetpack-From-Java-To-Kotlin/1836ce1d4435b34164045d8ec582a65f1e0aa895/version_config/settings.gradle
--------------------------------------------------------------------------------
/version_config/src/main/java/com/flywith24/version_config/BuildConfig.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.version_config
2 |
3 | /**
4 | * @author Flywith24
5 | * @date 2020/5/27
6 | * time 10:59
7 | * description
8 | */
9 | object BuildConfig {
10 | const val compileSdkVersion = 29
11 | const val buildToolsVersion = "29.0.3"
12 | const val minSdkVersion = 23
13 | const val targetSdkVersion = 29
14 | const val versionCode = 1
15 | const val versionName = "1.0"
16 | }
17 |
--------------------------------------------------------------------------------
/version_config/src/main/java/com/flywith24/version_config/VersionConfigPlugin.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.version_config
2 |
3 | import org.gradle.api.Plugin
4 | import org.gradle.api.Project
5 |
6 | /**
7 | * @author Flywith24
8 | * @date 2020/5/28
9 | * time 9:02
10 | * description
11 | * 依赖版本控制插件
12 | */
13 | class VersionConfigPlugin : Plugin {
14 | override fun apply(project: Project) {
15 | //公共配置
16 | }
17 | }
--------------------------------------------------------------------------------
/version_config/src/main/java/com/flywith24/version_config/dependencies/Google.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("SpellCheckingInspection")
2 |
3 | package com.flywith24.version_config.dependencies
4 |
5 | /**
6 | * @author Flywith24
7 | * @date 2020/3/5
8 | * time 21:09
9 | * description
10 | * google dependencis
11 | */
12 | object Google {
13 | const val material = "com.google.android.material:material:1.2.0-alpha05"
14 | const val gson = "com.google.code.gson:gson:2.8.6"
15 | }
--------------------------------------------------------------------------------
/version_config/src/main/java/com/flywith24/version_config/dependencies/Testing.kt:
--------------------------------------------------------------------------------
1 | package com.flywith24.version_config.dependencies
2 |
3 | /**
4 | * @author Flywith24
5 | * @date 2020/1/14
6 | * time 8:39
7 | * description
8 | * test dependencies
9 | */
10 | object Testing {
11 | const val jUnit = "junit:junit:4.12"
12 | const val androidJunit = "androidx.test.ext:junit:1.1.1"
13 | const val androidRunner = "androidx.test:runner:1.2.0"
14 | const val espresso = "androidx.test.espresso:espresso-core:3.2.0"
15 | }
--------------------------------------------------------------------------------
/version_config/src/main/java/com/flywith24/version_config/dependencies/ThirdParty.kt:
--------------------------------------------------------------------------------
1 | @file:Suppress("SpellCheckingInspection")
2 |
3 | package com.flywith24.version_config.dependencies
4 |
5 | /**
6 | * @author Flywith24
7 | * @date 2020/5/28
8 | * time 9:43
9 | * description
10 | * third party dependencies
11 | */
12 | object ThirdParty {
13 | const val materialiconlib = "net.steamcrafted:materialiconlib:1.1.5"
14 | const val permission = "com.yanzhenjie.permission:x:2.0.1"
15 |
16 | object Glide {
17 | private const val glide_version = "4.11.0"
18 | const val glide = "com.github.bumptech.glide:glide:$glide_version"
19 | const val compiler = "com.github.bumptech.glide:compiler:$glide_version"
20 | }
21 |
22 | object Archi {
23 | const val unPeekLiveData = "com.kunminx.archi:unpeek-livedata:4.4.1-beta1"
24 | }
25 |
26 | const val roundedImageView = "com.makeramen:roundedimageview:2.3.0"
27 |
28 | }
--------------------------------------------------------------------------------