From 9ae4ddd23ff4834b535fbd290fc1ed2cd206db09 Mon Sep 17 00:00:00 2001 From: Ztiany Date: Thu, 31 Oct 2019 21:00:21 +0800 Subject: [PATCH] Sword to Kotlin --- .../android/base/app/ApplicationDelegate.java | 116 --------- .../android/base/app/ApplicationDelegate.kt | 76 ++++++ .../com/android/base/app/BaseAppContext.java | 46 ---- .../com/android/base/app/BaseAppContext.kt | 55 +++++ .../com/android/base/app/CrashHandler.java | 113 --------- .../base/app/InjectorBaseAppContext.kt | 18 -- .../main/java/com/android/base/app/Sword.java | 230 ------------------ .../main/java/com/android/base/app/Sword.kt | 138 +++++++++++ .../base/app/fragment/BaseDialogFragment.kt | 7 +- .../android/base/app/fragment/BaseFragment.kt | 6 +- .../android/base/app/ui/LoadingViewFactory.kt | 9 - .../java/com/android/base/app/ui/UIKit.kt | 12 +- .../android/base/app/utils/CrashHandler.kt | 109 +++++++++ .../base/imageloader/ProgressManager.java | 2 + .../imageloader/ProgressResponseBody.java | 3 + .../java/com/android/base/rx/RxLiveStateEx.kt | 77 +----- .../java/com/android/base/rx/RxLivedata.kt | 77 +++++- ...pose.kt => RxLiveStateExForAutoDispose.kt} | 106 -------- .../autodispose/RxLivedataForAutoDispose.kt | 109 +++++++++ .../base/utils/android/views/TextViewEx.kt | 8 +- .../base/utils/upgrade/AppUpgradeChecker.kt | 4 +- .../widget/viewpager/BannerPagerAdapter.java | 6 +- .../java/com/android/base/rx/RxBusTest.java | 22 +- .../com/android/base/rx/TestApplication.java | 21 -- .../com/android/base/rx/TestBaseActivity.java | 29 --- .../com/android/base/rx/TestListFragment.java | 28 --- .../android/base/rx/TestStateFragment.java | 46 ---- 27 files changed, 598 insertions(+), 875 deletions(-) delete mode 100644 lib_base/src/main/java/com/android/base/app/ApplicationDelegate.java create mode 100644 lib_base/src/main/java/com/android/base/app/ApplicationDelegate.kt delete mode 100644 lib_base/src/main/java/com/android/base/app/BaseAppContext.java create mode 100644 lib_base/src/main/java/com/android/base/app/BaseAppContext.kt delete mode 100644 lib_base/src/main/java/com/android/base/app/CrashHandler.java delete mode 100644 lib_base/src/main/java/com/android/base/app/InjectorBaseAppContext.kt delete mode 100644 lib_base/src/main/java/com/android/base/app/Sword.java create mode 100644 lib_base/src/main/java/com/android/base/app/Sword.kt delete mode 100644 lib_base/src/main/java/com/android/base/app/ui/LoadingViewFactory.kt create mode 100644 lib_base/src/main/java/com/android/base/app/utils/CrashHandler.kt rename lib_base/src/main/java/com/android/base/rx/autodispose/{RxLiveStateExForAutodDispose.kt => RxLiveStateExForAutoDispose.kt} (56%) create mode 100644 lib_base/src/main/java/com/android/base/rx/autodispose/RxLivedataForAutoDispose.kt delete mode 100644 lib_base/src/test/java/com/android/base/rx/TestApplication.java delete mode 100644 lib_base/src/test/java/com/android/base/rx/TestBaseActivity.java delete mode 100644 lib_base/src/test/java/com/android/base/rx/TestListFragment.java delete mode 100644 lib_base/src/test/java/com/android/base/rx/TestStateFragment.java diff --git a/lib_base/src/main/java/com/android/base/app/ApplicationDelegate.java b/lib_base/src/main/java/com/android/base/app/ApplicationDelegate.java deleted file mode 100644 index b06284f..0000000 --- a/lib_base/src/main/java/com/android/base/app/ApplicationDelegate.java +++ /dev/null @@ -1,116 +0,0 @@ -package com.android.base.app; - -import android.app.Application; -import android.content.Context; -import android.content.IntentFilter; -import android.content.res.Configuration; -import android.net.ConnectivityManager; - -import com.android.base.receiver.NetStateReceiver; -import com.android.base.utils.BaseUtils; -import com.blankj.utilcode.util.AppUtils; -import com.blankj.utilcode.util.Utils; - -import java.util.concurrent.atomic.AtomicBoolean; - -import io.reactivex.Flowable; -import io.reactivex.processors.BehaviorProcessor; -import timber.log.Timber; - -/** - * @author Ztiany - * Email: ztiany3@gmail.com - * Date : 2018-10-12 18:19 - */ -@SuppressWarnings("WeakerAccess,unused") -public final class ApplicationDelegate { - - private Application mApplication; - - private CrashHandler mCrashHandler; - private BehaviorProcessor mAppStatus; - - private AtomicBoolean mOnCreateCalled = new AtomicBoolean(false); - private AtomicBoolean mOnAttachBaseCalled = new AtomicBoolean(false); - - ApplicationDelegate() { - } - - public void attachBaseContext(@SuppressWarnings("unused") Context base) { - if (!mOnAttachBaseCalled.compareAndSet(false, true)) { - throw new IllegalStateException("Can only be called once"); - } - //no op - } - - public void onCreate(Application application) { - if (!mOnCreateCalled.compareAndSet(false, true)) { - throw new IllegalStateException("Can only be called once"); - } - mApplication = application; - //工具类初始化 - BaseUtils.init(application); - //异常日志记录 - mCrashHandler = CrashHandler.register(application); - //网络状态 - listenNetworkState(); - //App前台后台 - listenActivityLifecycleCallbacks(); - } - - public void onTerminate() { - //no op - } - - public void onConfigurationChanged(Configuration newConfig) { - //no op - } - - public void onTrimMemory(int level) { - //no op - } - - public void onLowMemory() { - //no op - } - - private void listenNetworkState() { - NetStateReceiver netStateReceiver = new NetStateReceiver(); - mApplication.registerReceiver(netStateReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); - } - - private void listenActivityLifecycleCallbacks() { - mAppStatus = BehaviorProcessor.create(); - AppUtils.registerAppStatusChangedListener(this, new Utils.OnAppStatusChangedListener() { - @Override - public void onForeground() { - Timber.d("app进入前台"); - mAppStatus.onNext(true); - } - - @Override - public void onBackground() { - Timber.d("app进入后台"); - mAppStatus.onNext(false); - } - }); - } - - /** - * 获取可观察的 app 生命周期 - */ - Flowable appAppState() { - return mAppStatus; - } - - void setCrashProcessor(Sword.CrashProcessor crashProcessor) { - if (mCrashHandler != null) { - mCrashHandler.setCrashProcessor(crashProcessor); - } - } - - Application getApplication() { - return mApplication; - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/ApplicationDelegate.kt b/lib_base/src/main/java/com/android/base/app/ApplicationDelegate.kt new file mode 100644 index 0000000..a701e45 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/ApplicationDelegate.kt @@ -0,0 +1,76 @@ +package com.android.base.app + +import android.app.Application +import android.content.Context +import android.content.IntentFilter +import android.content.res.Configuration +import android.net.ConnectivityManager +import com.android.base.app.utils.CrashHandler +import com.android.base.receiver.NetStateReceiver +import com.android.base.utils.BaseUtils +import com.blankj.utilcode.util.AppUtils +import com.blankj.utilcode.util.Utils.OnAppStatusChangedListener +import io.reactivex.processors.BehaviorProcessor +import timber.log.Timber +import java.util.concurrent.atomic.AtomicBoolean + +/** + * @author Ztiany + * Email: ztiany3@gmail.com + * Date : 2018-10-12 18:19 + */ +class ApplicationDelegate internal constructor() { + + lateinit var application: Application + private lateinit var crashHandler: CrashHandler + + /** 获取可观察的 app 生命周期 */ + val appStatus: BehaviorProcessor = BehaviorProcessor.create() + + private val onCreateCalled = AtomicBoolean(false) + private val onAttachBaseCalled = AtomicBoolean(false) + + fun attachBaseContext(base: Context) { + check(onAttachBaseCalled.compareAndSet(false, true)) { "Can only be called once" } + } + + fun onCreate(application: Application) { + check(onCreateCalled.compareAndSet(false, true)) { "Can only be called once" } + this.application = application + //工具类初始化 + BaseUtils.init(application) + //异常日志记录 + crashHandler = CrashHandler.register(application) + //网络状态 + application.registerReceiver(NetStateReceiver(), IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)) + //App前台后台 + listenActivityLifecycleCallbacks() + } + + fun onTerminate() {} + + fun onConfigurationChanged(newConfig: Configuration) {} + + fun onTrimMemory(level: Int) {} + + fun onLowMemory() {} + + private fun listenActivityLifecycleCallbacks() { + AppUtils.registerAppStatusChangedListener(this, object : OnAppStatusChangedListener { + override fun onForeground() { + Timber.d("app进入前台") + appStatus.onNext(true) + } + + override fun onBackground() { + Timber.d("app进入后台") + appStatus.onNext(false) + } + }) + } + + internal fun setCrashProcessor(crashProcessor: CrashProcessor) { + crashHandler.setCrashProcessor(crashProcessor) + } + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/BaseAppContext.java b/lib_base/src/main/java/com/android/base/app/BaseAppContext.java deleted file mode 100644 index cf879b8..0000000 --- a/lib_base/src/main/java/com/android/base/app/BaseAppContext.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.android.base.app; - -import android.app.Application; -import android.content.Context; -import android.content.res.Configuration; - - -public class BaseAppContext extends Application { - - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(base); - Sword.get().getApplicationDelegate().attachBaseContext(base); - } - - @Override - public void onCreate() { - super.onCreate(); - Sword.get().getApplicationDelegate().onCreate(this); - } - - @Override - public void onLowMemory() { - super.onLowMemory(); - Sword.get().getApplicationDelegate().onLowMemory(); - } - - @Override - public void onTrimMemory(int level) { - super.onTrimMemory(level); - Sword.get().getApplicationDelegate().onTrimMemory(level); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - Sword.get().getApplicationDelegate().onConfigurationChanged(newConfig); - } - - @Override - public void onTerminate() { - super.onTerminate(); - Sword.get().getApplicationDelegate().onTerminate(); - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/BaseAppContext.kt b/lib_base/src/main/java/com/android/base/app/BaseAppContext.kt new file mode 100644 index 0000000..b53f153 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/BaseAppContext.kt @@ -0,0 +1,55 @@ +package com.android.base.app + +import android.app.Application +import android.content.Context +import android.content.res.Configuration +import dagger.android.DispatchingAndroidInjector +import dagger.android.HasAndroidInjector +import javax.inject.Inject + +open class BaseAppContext : Application() { + + override fun attachBaseContext(base: Context) { + super.attachBaseContext(base) + Sword.applicationDelegate.attachBaseContext(base) + } + + override fun onCreate() { + super.onCreate() + Sword.applicationDelegate.onCreate(this) + } + + override fun onLowMemory() { + super.onLowMemory() + Sword.applicationDelegate.onLowMemory() + } + + override fun onTrimMemory(level: Int) { + super.onTrimMemory(level) + Sword.applicationDelegate.onTrimMemory(level) + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + Sword.applicationDelegate.onConfigurationChanged(newConfig) + } + + override fun onTerminate() { + super.onTerminate() + Sword.applicationDelegate.onTerminate() + } + +} + +/** + *@author Ztiany + * Email: ztiany3@gmail.com + * Date : 2019-10-12 10:59 + */ +open class InjectorBaseAppContext : BaseAppContext(), HasAndroidInjector { + + @Inject lateinit var androidInjector: DispatchingAndroidInjector + + override fun androidInjector() = androidInjector + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/CrashHandler.java b/lib_base/src/main/java/com/android/base/app/CrashHandler.java deleted file mode 100644 index 83e2c33..0000000 --- a/lib_base/src/main/java/com/android/base/app/CrashHandler.java +++ /dev/null @@ -1,113 +0,0 @@ -package com.android.base.app; - -import android.annotation.SuppressLint; -import android.app.Application; -import android.content.Context; -import android.os.Build; -import android.os.Process; - -import com.blankj.utilcode.util.AppUtils; - -import java.io.File; -import java.io.PrintStream; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -import timber.log.Timber; - -/** - * 全局异常处理 - */ -final class CrashHandler implements Thread.UncaughtExceptionHandler { - - private Context mContext; - private Sword.CrashProcessor mCrashProcessor; - - public static CrashHandler register(Application application) { - CrashHandler crashHandler = new CrashHandler(application); - Thread.setDefaultUncaughtExceptionHandler(crashHandler); - return crashHandler; - } - - void setCrashProcessor(Sword.CrashProcessor crashProcessor) { - mCrashProcessor = crashProcessor; - } - - private CrashHandler(Context context) { - this.mContext = context; - } - - @Override - public void uncaughtException(Thread thread, Throwable ex) { - - if (mCrashProcessor != null) { - mCrashProcessor.uncaughtException(thread, ex); - } else { - // 收集异常信息,写入到sd卡 - restoreCrash(thread, ex); - //退出 - killProcess(); - } - } - - private void restoreCrash(@SuppressWarnings("unused") Thread thread, Throwable ex) { - ex.printStackTrace(System.err); - // 收集异常信息,写入到sd卡 - File dir = new File(mContext.getExternalFilesDir(null) + File.separator + "crash"); - - if (!dir.exists()) { - boolean mkdirs = dir.mkdirs(); - if (!mkdirs) { - Timber.e("CrashHandler create dir fail"); - return; - } - } - - try { - @SuppressLint("SimpleDateFormat") - DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - String name = dateFormat.format(new Date(System.currentTimeMillis())) + ".log"; - File fileName = new File(dir, name); - if (!fileName.exists()) { - @SuppressWarnings("unused") - boolean newFile = fileName.createNewFile(); - } - - PrintStream err = new PrintStream(fileName); - - err.println("--------------------------------AppInfo--------------------------------"); - err.println("AndroidVersion: " + AppUtils.getAppVersionName()); - err.println(); - err.println(); - err.println("--------------------------------SystemInfo:--------------------------------"); - err.println("Product: " + android.os.Build.PRODUCT); - err.println("CPU_ABI: " + android.os.Build.CPU_ABI); - err.println("TAGS: " + android.os.Build.TAGS); - err.println("VERSION_CODES.BASE:" + android.os.Build.VERSION_CODES.BASE); - err.println("MODEL: " + android.os.Build.MODEL); - err.println("SDK: " + Build.VERSION.SDK_INT); - err.println("VERSION.RELEASE: " + android.os.Build.VERSION.RELEASE); - err.println("DEVICE: " + android.os.Build.DEVICE); - err.println("DISPLAY: " + android.os.Build.DISPLAY); - err.println("BRAND: " + android.os.Build.BRAND); - err.println("BOARD: " + android.os.Build.BOARD); - err.println("FINGERPRINT: " + android.os.Build.FINGERPRINT); - err.println("ID: " + android.os.Build.ID); - err.println("MANUFACTURER: " + android.os.Build.MANUFACTURER); - err.println("USER: " + android.os.Build.USER); - err.println(); - err.println(); - err.println("--------------------------------CrashContent--------------------------------"); - ex.printStackTrace(err); - err.println(); - } catch (Exception e) { - e.printStackTrace(); - } - } - - private void killProcess() { - Process.killProcess(Process.myPid()); - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/InjectorBaseAppContext.kt b/lib_base/src/main/java/com/android/base/app/InjectorBaseAppContext.kt deleted file mode 100644 index f887a19..0000000 --- a/lib_base/src/main/java/com/android/base/app/InjectorBaseAppContext.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.android.base.app - -import dagger.android.DispatchingAndroidInjector -import dagger.android.HasAndroidInjector -import javax.inject.Inject - -/** - *@author Ztiany - * Email: ztiany3@gmail.com - * Date : 2019-10-12 10:59 - */ -open class InjectorBaseAppContext : BaseAppContext(), HasAndroidInjector { - - @Inject lateinit var androidInjector: DispatchingAndroidInjector - - override fun androidInjector() = androidInjector - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/Sword.java b/lib_base/src/main/java/com/android/base/app/Sword.java deleted file mode 100644 index 3b38a58..0000000 --- a/lib_base/src/main/java/com/android/base/app/Sword.java +++ /dev/null @@ -1,230 +0,0 @@ -package com.android.base.app; - -import android.app.Activity; -import android.app.Application; -import android.content.Context; -import android.os.Bundle; - -import com.android.base.app.dagger.Injectable; -import com.android.base.app.fragment.animator.FragmentAnimator; -import com.android.base.app.fragment.tools.FragmentConfig; -import com.android.base.app.ui.LoadingViewFactory; -import com.android.base.app.ui.PageNumber; -import com.android.base.app.ui.RefreshLoadViewFactory; -import com.android.base.app.ui.RefreshViewFactory; -import com.android.base.interfaces.ActivityLifecycleCallbacksAdapter; -import com.android.base.receiver.NetworkState; -import com.blankj.utilcode.util.ActivityUtils; -import com.blankj.utilcode.util.AppUtils; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.UiThread; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; -import dagger.android.AndroidInjection; -import dagger.android.support.AndroidSupportInjection; -import io.reactivex.Flowable; - -/** - * useful tools for android development, just like a sword. - * - * @author Ztiany - * Email: ztiany3@gmail.com - * Date : 2018-04-16 17:12 - */ -@SuppressWarnings("unused") -@UiThread -public final class Sword { - - private static final Sword ONLY_BASE = new Sword(); - - private Sword() { - mApplicationDelegate = new ApplicationDelegate(); - } - - public static Sword get() { - return ONLY_BASE; - } - - /** - * LoadingView - */ - private LoadingViewFactory mLoadingViewFactory; - - /** - * Application lifecycle delegate - */ - private ApplicationDelegate mApplicationDelegate; - - /** - * 错误类型检查 - */ - private ErrorClassifier mErrorClassifier; - - /** - * dialog 最小展示时间 - */ - private long minimumShowingDialogMills; - - /** - * 获取 Application 代理 - */ - public ApplicationDelegate getApplicationDelegate() { - return mApplicationDelegate; - } - - public Sword registerLoadingFactory(LoadingViewFactory loadingViewFactory) { - if (mLoadingViewFactory != null) { - throw new UnsupportedOperationException("LoadingViewFactory had already set"); - } - mLoadingViewFactory = loadingViewFactory; - return this; - } - - public LoadingViewFactory getLoadingViewFactory() { - if (mLoadingViewFactory == null) { - throw new NullPointerException("you have not set the LoadingViewFactory by AndroidBase"); - } - return mLoadingViewFactory; - } - - public Flowable networkState() { - return NetworkState.observableState(); - } - - - public interface CrashProcessor { - void uncaughtException(Thread thread, Throwable ex); - } - - public Sword setCrashProcessor(CrashProcessor crashProcessor) { - mApplicationDelegate.setCrashProcessor(crashProcessor); - return this; - } - - public Sword setDefaultPageStart(int pageStart) { - PageNumber.setDefaultPageStart(pageStart); - return this; - } - - public Sword setDefaultPageSize(int defaultPageSize) { - PageNumber.setDefaultPageSize(defaultPageSize); - return this; - } - - /** - * 给 {@link com.android.base.app.fragment.tools.Fragments } 设置一个默认的容器 id,在使用 其相关方法而没有传入特定的容器 id 时,则使用默认的容器 id。 - * - * @param defaultContainerId 容器id - */ - public Sword setDefaultFragmentContainerId(int defaultContainerId) { - FragmentConfig.setDefaultContainerId(defaultContainerId); - return this; - } - - /** - * 设置 dialog 最小展示时间,建议不超过 1 秒 - */ - public Sword setMinimumShowingDialogMills(long minimumShowingDialogMills) { - this.minimumShowingDialogMills = minimumShowingDialogMills; - return this; - } - - public Sword setDefaultFragmentAnimator(FragmentAnimator animator) { - FragmentConfig.setDefaultFragmentAnimator(animator); - return this; - } - - public Sword enableAutoInject() { - Application.ActivityLifecycleCallbacks activityLifecycleCallbacks = new ActivityLifecycleCallbacksAdapter() { - - @Override - public void onActivityCreated(Activity activity, Bundle savedInstanceState) { - if (activity instanceof Injectable) { - if (((Injectable) activity).enableInject()) { - AndroidInjection.inject(activity); - if (activity instanceof FragmentActivity) { - handedFragmentInject((FragmentActivity) activity); - } - } - } - } - - private void handedFragmentInject(FragmentActivity activity) { - activity.getSupportFragmentManager().registerFragmentLifecycleCallbacks(new FragmentManager.FragmentLifecycleCallbacks() { - @Override - public void onFragmentAttached(@NonNull FragmentManager fm, @NonNull Fragment f, @NonNull Context context) { - if (f instanceof Injectable) { - if (((Injectable) f).enableInject()) { - AndroidSupportInjection.inject(f); - } - } - } - }, true); - } - }; - mApplicationDelegate.getApplication().registerActivityLifecycleCallbacks(activityLifecycleCallbacks); - return this; - } - - /** - * 获取可观察的 app 生命周期 - */ - public Flowable appState() { - return mApplicationDelegate.appAppState(); - } - - /** - * 获取当前resume的Activity - * - * @return activity - */ - @Nullable - public Activity getTopActivity() { - return ActivityUtils.getTopActivity(); - } - - /** - * App是否在前台运行 - * - * @return true 表示App在前台运行 - */ - public boolean isForeground() { - return AppUtils.isAppForeground(); - } - - public interface ErrorClassifier { - boolean isNetworkError(Throwable throwable); - - boolean isServerError(Throwable throwable); - } - - public Sword setErrorClassifier(ErrorClassifier errorClassifier) { - if (mErrorClassifier != null) { - throw new UnsupportedOperationException("ErrorClassifier had already set"); - } - mErrorClassifier = errorClassifier; - return this; - } - - public ErrorClassifier errorClassifier() { - return mErrorClassifier; - } - - public Sword registerRefreshLoadViewFactory(RefreshLoadViewFactory.Factory factory) { - RefreshLoadViewFactory.registerFactory(factory); - return this; - } - - public Sword registerRefreshViewFactory(RefreshViewFactory.Factory factory) { - RefreshViewFactory.registerFactory(factory); - return this; - } - - public long minimumShowingDialogMills() { - return minimumShowingDialogMills; - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/Sword.kt b/lib_base/src/main/java/com/android/base/app/Sword.kt new file mode 100644 index 0000000..4a6bed6 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/Sword.kt @@ -0,0 +1,138 @@ +package com.android.base.app + +import android.app.Activity +import android.app.Application.ActivityLifecycleCallbacks +import android.content.Context +import android.os.Bundle +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentActivity +import androidx.fragment.app.FragmentManager +import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks +import com.android.base.app.dagger.Injectable +import com.android.base.app.fragment.animator.FragmentAnimator +import com.android.base.app.fragment.tools.FragmentConfig +import com.android.base.app.ui.LoadingView +import com.android.base.app.ui.PageNumber +import com.android.base.app.ui.RefreshLoadViewFactory +import com.android.base.app.ui.RefreshLoadViewFactory.Factory +import com.android.base.app.ui.RefreshViewFactory +import com.android.base.interfaces.ActivityLifecycleCallbacksAdapter +import com.android.base.receiver.NetworkState +import com.blankj.utilcode.util.ActivityUtils +import com.blankj.utilcode.util.AppUtils +import dagger.android.AndroidInjection +import dagger.android.support.AndroidSupportInjection +import io.reactivex.Flowable + +/** + * useful tools for android development, just like a sword. + * + * @author Ztiany + * Email: ztiany3@gmail.com + * Date : 2018-04-16 17:12 + */ +object Sword { + + /** Application lifecycle delegate */ + val applicationDelegate = ApplicationDelegate() + + /** 错误类型分类器 */ + var errorClassifier: ErrorClassifier? = null + + /** dialog 最小展示时间 */ + var minimumShowingDialogMills: Long = 0 + + /** 用于创建 LoadingView*/ + var loadingViewFactory: ((Context) -> LoadingView)? = null + + /**网络状态监听器*/ + fun networkState(): Flowable = NetworkState.observableState() + + fun setCrashProcessor(crashProcessor: CrashProcessor): Sword { + applicationDelegate.setCrashProcessor(crashProcessor) + return this + } + + fun setDefaultPageStart(pageStart: Int): Sword { + PageNumber.setDefaultPageStart(pageStart) + return this + } + + fun setDefaultPageSize(defaultPageSize: Int): Sword { + PageNumber.setDefaultPageSize(defaultPageSize) + return this + } + + /** 设置一个默认的布局 id,在使用 Fragments 中相关方法时,如果没有传入特定的容器 id 时,则使用设置的默认布局 id。 */ + fun setDefaultFragmentContainerId(defaultContainerId: Int): Sword { + FragmentConfig.setDefaultContainerId(defaultContainerId) + return this + } + + /**设置默认的 Fragment 转场动画*/ + fun setDefaultFragmentAnimator(animator: FragmentAnimator?): Sword { + FragmentConfig.setDefaultFragmentAnimator(animator) + return this + } + + fun enableAutoInject(): Sword { + val activityLifecycleCallbacks: ActivityLifecycleCallbacks = object : ActivityLifecycleCallbacksAdapter { + override fun onActivityCreated(activity: Activity?, savedInstanceState: Bundle?) { + if (activity is Injectable) { + if ((activity as Injectable).enableInject()) { + AndroidInjection.inject(activity) + if (activity is FragmentActivity) { + handedFragmentInject(activity as FragmentActivity) + } + } + } + } + + private fun handedFragmentInject(activity: FragmentActivity) { + activity.supportFragmentManager.registerFragmentLifecycleCallbacks(object : FragmentLifecycleCallbacks() { + override fun onFragmentAttached(fm: FragmentManager, f: Fragment, context: Context) { + if (f is Injectable) { + if ((f as Injectable).enableInject()) { + AndroidSupportInjection.inject(f) + } + } + } + }, true) + } + } + applicationDelegate.application.registerActivityLifecycleCallbacks(activityLifecycleCallbacks) + return this + } + + /** 获取可观察的 app 生命周期 */ + val appState: Flowable + get() = applicationDelegate.appStatus + + /** 获取当前 resume 的 Activity */ + val topActivity: Activity? + get() = ActivityUtils.getTopActivity() + + /** App是否在前台运行 */ + val isForeground: Boolean + get() = AppUtils.isAppForeground() + + fun registerRefreshLoadViewFactory(factory: Factory): Sword { + RefreshLoadViewFactory.registerFactory(factory) + return this + } + + fun registerRefreshViewFactory(factory: RefreshViewFactory.Factory): Sword { + RefreshViewFactory.registerFactory(factory) + return this + } + +} + +interface CrashProcessor { + fun uncaughtException(thread: Thread, ex: Throwable) +} + +interface ErrorClassifier { + fun isNetworkError(throwable: Throwable): Boolean + fun isServerError(throwable: Throwable): Boolean +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/BaseDialogFragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/BaseDialogFragment.kt index a3d59c5..335158d 100644 --- a/lib_base/src/main/java/com/android/base/app/fragment/BaseDialogFragment.kt +++ b/lib_base/src/main/java/com/android/base/app/fragment/BaseDialogFragment.kt @@ -225,10 +225,8 @@ open class BaseDialogFragment : AppCompatDialogFragment(), LoadingView, OnBackPr return if (loadingViewImpl != null) { loadingViewImpl } else { - loadingView = onCreateLoadingView() - ?: Sword.get().loadingViewFactory.createLoadingDelegate(requireContext()) - loadingView - ?: throw NullPointerException("you need to config LoadingViewFactory") + loadingView = onCreateLoadingView() ?: Sword.loadingViewFactory?.invoke(requireContext()) + loadingView ?: throw NullPointerException("you need to config LoadingViewFactory in Sword or implement onCreateLoadingView.") } } @@ -236,7 +234,6 @@ open class BaseDialogFragment : AppCompatDialogFragment(), LoadingView, OnBackPr return null } - override fun showLoadingDialog() { recentShowingDialogTime = System.currentTimeMillis() loadingView().showLoadingDialog(true) diff --git a/lib_base/src/main/java/com/android/base/app/fragment/BaseFragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/BaseFragment.kt index efdddf1..bb92e95 100644 --- a/lib_base/src/main/java/com/android/base/app/fragment/BaseFragment.kt +++ b/lib_base/src/main/java/com/android/base/app/fragment/BaseFragment.kt @@ -236,10 +236,8 @@ open class BaseFragment : Fragment(), LoadingView, OnBackPressListener, Fragment return if (loadingViewImpl != null) { loadingViewImpl } else { - loadingView = onCreateLoadingView() - ?: Sword.get().loadingViewFactory.createLoadingDelegate(requireContext()) - loadingView - ?: throw NullPointerException("you need to config LoadingViewFactory") + loadingView = onCreateLoadingView() ?: Sword.loadingViewFactory?.invoke(requireContext()) + loadingView ?: throw NullPointerException("you need to config LoadingViewFactory in Sword or implement onCreateLoadingView.") } } diff --git a/lib_base/src/main/java/com/android/base/app/ui/LoadingViewFactory.kt b/lib_base/src/main/java/com/android/base/app/ui/LoadingViewFactory.kt deleted file mode 100644 index a72fcb3..0000000 --- a/lib_base/src/main/java/com/android/base/app/ui/LoadingViewFactory.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.android.base.app.ui - -import android.content.Context - -interface LoadingViewFactory { - - fun createLoadingDelegate(context: Context): LoadingView - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/ui/UIKit.kt b/lib_base/src/main/java/com/android/base/app/ui/UIKit.kt index badf0be..09e787b 100644 --- a/lib_base/src/main/java/com/android/base/app/ui/UIKit.kt +++ b/lib_base/src/main/java/com/android/base/app/ui/UIKit.kt @@ -31,7 +31,7 @@ fun H.handleLiveState( when { state.isError -> { Timber.d("handleLiveState -> isError") - dismissLoadingDialog(Sword.get().minimumShowingDialogMills()) { + dismissLoadingDialog(Sword.minimumShowingDialogMills) { if (onError != null) { onError(state.error()) } else { @@ -45,7 +45,7 @@ fun H.handleLiveState( } state.isSuccess -> { Timber.d("handleLiveState -> isSuccess") - dismissLoadingDialog(Sword.get().minimumShowingDialogMills()) { + dismissLoadingDialog(Sword.minimumShowingDialogMills) { onSuccess(state.get()) } }//success end @@ -78,7 +78,7 @@ fun LoadingView.handleState( when { state.isError -> { Timber.d("handleState -> isError") - dismissLoadingDialog(Sword.get().minimumShowingDialogMills()) { + dismissLoadingDialog(Sword.minimumShowingDialogMills) { stateHandler.onError?.invoke(state.error()) } } @@ -88,7 +88,7 @@ fun LoadingView.handleState( } state.isSuccess -> { Timber.d("handleState -> isSuccess") - dismissLoadingDialog(Sword.get().minimumShowingDialogMills()) { + dismissLoadingDialog(Sword.minimumShowingDialogMills) { stateHandler.onSuccess?.invoke(state.get()) if (state.hasData()) { stateHandler.onSuccessWithData?.invoke(state.data()) @@ -134,7 +134,7 @@ fun RefreshListLayout<*>.handleListError(throwable: Throwable) { loadMoreFailed() } if (isEmpty) { - val errorTypeClassifier = Sword.get().errorClassifier() + val errorTypeClassifier = Sword.errorClassifier if (errorTypeClassifier != null) { when { errorTypeClassifier.isNetworkError(throwable) -> showNetErrorLayout() @@ -284,7 +284,7 @@ fun RefreshStateLayout.handleResultError(throwable: Throwable) { if (isRefreshing) { refreshCompleted() } - val errorTypeClassifier = Sword.get().errorClassifier() + val errorTypeClassifier = Sword.errorClassifier if (errorTypeClassifier != null) { when { errorTypeClassifier.isNetworkError(throwable) -> { diff --git a/lib_base/src/main/java/com/android/base/app/utils/CrashHandler.kt b/lib_base/src/main/java/com/android/base/app/utils/CrashHandler.kt new file mode 100644 index 0000000..438c7ef --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/utils/CrashHandler.kt @@ -0,0 +1,109 @@ +package com.android.base.app.utils + +import android.annotation.SuppressLint +import android.app.Application +import android.content.Context +import android.os.Build +import android.os.Build.VERSION +import android.os.Build.VERSION_CODES +import android.os.Process +import com.android.base.app.CrashProcessor +import com.blankj.utilcode.util.AppUtils +import timber.log.Timber +import java.io.File +import java.io.PrintStream +import java.lang.Thread.UncaughtExceptionHandler +import java.text.DateFormat +import java.text.SimpleDateFormat +import java.util.* + +/** + * 全局异常处理 + */ +internal class CrashHandler private constructor( + private val context: Context +) : UncaughtExceptionHandler { + + private var _crashProcessor: CrashProcessor? = null + + fun setCrashProcessor(crashProcessor: CrashProcessor) { + _crashProcessor = crashProcessor + } + + override fun uncaughtException(thread: Thread, ex: Throwable) { + val crashProcessor = _crashProcessor + if (crashProcessor != null) { + crashProcessor.uncaughtException(thread, ex) + } else { + // 收集异常信息,写入到sd卡 + restoreCrash(thread, ex) + //退出 + killProcess() + } + } + + private fun restoreCrash(thread: Thread, ex: Throwable) { + ex.printStackTrace(System.err) + // 收集异常信息,写入到sd卡 + val externalFilesDir = context.getExternalFilesDir(null) ?: return + val dir = File(externalFilesDir.toString() + File.separator + "crash") + + if (!dir.exists()) { + val mkdirs = dir.mkdirs() + if (!mkdirs) { + Timber.e("CrashHandler create dir fail") + return + } + } + + try { + @SuppressLint("SimpleDateFormat") val dateFormat: DateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") + val name = dateFormat.format(Date(System.currentTimeMillis())) + ".log" + val targetFile = File(dir, name) + if (!targetFile.exists()) { + targetFile.createNewFile() + } + val err = PrintStream(targetFile) + err.println("--------------------------------AppInfo--------------------------------") + err.println("AndroidVersion: " + AppUtils.getAppVersionName()) + err.println() + err.println() + err.println("--------------------------------SystemInfo:--------------------------------") + err.println("Product: " + Build.PRODUCT) + err.println("CPU_ABI: " + Build.CPU_ABI) + err.println("TAGS: " + Build.TAGS) + err.println("VERSION_CODES.BASE:" + VERSION_CODES.BASE) + err.println("MODEL: " + Build.MODEL) + err.println("SDK: " + VERSION.SDK_INT) + err.println("VERSION.RELEASE: " + VERSION.RELEASE) + err.println("DEVICE: " + Build.DEVICE) + err.println("DISPLAY: " + Build.DISPLAY) + err.println("BRAND: " + Build.BRAND) + err.println("BOARD: " + Build.BOARD) + err.println("FINGERPRINT: " + Build.FINGERPRINT) + err.println("ID: " + Build.ID) + err.println("MANUFACTURER: " + Build.MANUFACTURER) + err.println("USER: " + Build.USER) + err.println() + err.println() + err.println("--------------------------------CrashContent--------------------------------") + ex.printStackTrace(err) + err.println() + } catch (e: Exception) { + e.printStackTrace() + } + } + + private fun killProcess() { + Process.killProcess(Process.myPid()) + } + + companion object { + fun register(application: Application): CrashHandler { + val crashHandler = CrashHandler(application) + Thread.setDefaultUncaughtExceptionHandler(crashHandler) + return crashHandler + } + } + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/imageloader/ProgressManager.java b/lib_base/src/main/java/com/android/base/imageloader/ProgressManager.java index 00c3291..3fb7c73 100644 --- a/lib_base/src/main/java/com/android/base/imageloader/ProgressManager.java +++ b/lib_base/src/main/java/com/android/base/imageloader/ProgressManager.java @@ -56,6 +56,7 @@ final class ProgressManager { //multi List> weakReferences = mMultiResponseListeners.get(url); if (!Checker.isEmpty(weakReferences)) { + assert weakReferences != null; for (WeakReference weakReference : weakReferences) { ProgressListener progressListener = weakReference.get(); if (progressListener != null) { @@ -78,6 +79,7 @@ final class ProgressManager { //multi List> weakReferences = mMultiResponseListeners.get(url); if (!Checker.isEmpty(weakReferences)) { + assert weakReferences != null; for (WeakReference weakReference : weakReferences) { ProgressListener progressListener = weakReference.get(); if (progressListener != null) { diff --git a/lib_base/src/main/java/com/android/base/imageloader/ProgressResponseBody.java b/lib_base/src/main/java/com/android/base/imageloader/ProgressResponseBody.java index 24c5732..b49590b 100644 --- a/lib_base/src/main/java/com/android/base/imageloader/ProgressResponseBody.java +++ b/lib_base/src/main/java/com/android/base/imageloader/ProgressResponseBody.java @@ -47,6 +47,7 @@ abstract class ProgressResponseBody extends ResponseBody { private Source source(Source source) { return new ForwardingSource(source) { + private long mContentLength; private long totalBytesRead = 0L; private long lastRefreshTime = 0L; //最后一次刷新的时间 @@ -54,6 +55,7 @@ abstract class ProgressResponseBody extends ResponseBody { @Override public long read(@NonNull Buffer sink, long byteCount) throws IOException { long bytesRead; + try { bytesRead = super.read(sink, byteCount); } catch (IOException e) { @@ -69,6 +71,7 @@ abstract class ProgressResponseBody extends ResponseBody { // read() returns the number of bytes read, or -1 if this source is exhausted. totalBytesRead += bytesRead != -1 ? bytesRead : 0; + long curTime = SystemClock.elapsedRealtime(); long intervalTime = curTime - lastRefreshTime; diff --git a/lib_base/src/main/java/com/android/base/rx/RxLiveStateEx.kt b/lib_base/src/main/java/com/android/base/rx/RxLiveStateEx.kt index aa98469..210de2f 100644 --- a/lib_base/src/main/java/com/android/base/rx/RxLiveStateEx.kt +++ b/lib_base/src/main/java/com/android/base/rx/RxLiveStateEx.kt @@ -1,6 +1,5 @@ package com.android.base.rx -import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import com.android.base.data.State import com.github.dmstocking.optional.java.util.Optional @@ -130,78 +129,4 @@ fun Completable.subscribeWithLiveData(liveData: MutableLiveData>, p liveData.postValue(State.error(it)) } ) -} - -//----------------------------------------------------------------------------------------- - -fun Observable.toResourceLiveData(): LiveData> { - val mutableLiveData = MutableLiveData>() - mutableLiveData.value = State.loading() - subscribe( - { - mutableLiveData.postValue(State.success(it)) - }, - { - mutableLiveData.postValue(State.error(it)) - } - ) - return mutableLiveData -} - -fun Observable>.optionalToResourceLiveData(): LiveData> { - val mutableLiveData = MutableLiveData>() - mutableLiveData.value = State.loading() - subscribe( - { - mutableLiveData.postValue(State.success(it.orElse(null))) - }, - { - mutableLiveData.postValue(State.error(it)) - } - ) - return mutableLiveData -} - -fun Flowable.toResourceLiveData(): LiveData> { - val mutableLiveData = MutableLiveData>() - mutableLiveData.value = State.loading() - subscribe( - { - mutableLiveData.postValue(State.success(it)) - }, - { - mutableLiveData.postValue(State.error(it)) - } - ) - return mutableLiveData -} - -fun Flowable>.optionalToResourceLiveData(): LiveData> { - val mutableLiveData = MutableLiveData>() - mutableLiveData.value = State.loading() - subscribe( - { - mutableLiveData.postValue(State.success(it.orElse(null))) - }, - { - mutableLiveData.postValue(State.error(it)) - } - ) - return mutableLiveData -} - -fun Completable.toResourceLiveData(): LiveData> { - val mutableLiveData = MutableLiveData>() - mutableLiveData.value = State.loading() - subscribe( - { - mutableLiveData.postValue(State.success()) - }, - { - mutableLiveData.postValue(State.error(it)) - } - ) - return mutableLiveData -} - -//----------------------------------------------------------------------------------------- +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/rx/RxLivedata.kt b/lib_base/src/main/java/com/android/base/rx/RxLivedata.kt index b8e3349..3b28fe5 100644 --- a/lib_base/src/main/java/com/android/base/rx/RxLivedata.kt +++ b/lib_base/src/main/java/com/android/base/rx/RxLivedata.kt @@ -2,10 +2,79 @@ package com.android.base.rx import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import io.reactivex.Flowable -import io.reactivex.Maybe -import io.reactivex.Observable -import io.reactivex.Single +import com.android.base.data.State +import com.github.dmstocking.optional.java.util.Optional +import io.reactivex.* + +fun Observable.toResourceLiveData(): LiveData> { + val mutableLiveData = MutableLiveData>() + mutableLiveData.value = State.loading() + subscribe( + { + mutableLiveData.postValue(State.success(it)) + }, + { + mutableLiveData.postValue(State.error(it)) + } + ) + return mutableLiveData +} + +fun Observable>.optionalToResourceLiveData(): LiveData> { + val mutableLiveData = MutableLiveData>() + mutableLiveData.value = State.loading() + subscribe( + { + mutableLiveData.postValue(State.success(it.orElse(null))) + }, + { + mutableLiveData.postValue(State.error(it)) + } + ) + return mutableLiveData +} + +fun Flowable.toResourceLiveData(): LiveData> { + val mutableLiveData = MutableLiveData>() + mutableLiveData.value = State.loading() + subscribe( + { + mutableLiveData.postValue(State.success(it)) + }, + { + mutableLiveData.postValue(State.error(it)) + } + ) + return mutableLiveData +} + +fun Flowable>.optionalToResourceLiveData(): LiveData> { + val mutableLiveData = MutableLiveData>() + mutableLiveData.value = State.loading() + subscribe( + { + mutableLiveData.postValue(State.success(it.orElse(null))) + }, + { + mutableLiveData.postValue(State.error(it)) + } + ) + return mutableLiveData +} + +fun Completable.toResourceLiveData(): LiveData> { + val mutableLiveData = MutableLiveData>() + mutableLiveData.value = State.loading() + subscribe( + { + mutableLiveData.postValue(State.success()) + }, + { + mutableLiveData.postValue(State.error(it)) + } + ) + return mutableLiveData +} fun Observable.toLiveData(): LiveData { val liveData = MutableLiveData() diff --git a/lib_base/src/main/java/com/android/base/rx/autodispose/RxLiveStateExForAutodDispose.kt b/lib_base/src/main/java/com/android/base/rx/autodispose/RxLiveStateExForAutoDispose.kt similarity index 56% rename from lib_base/src/main/java/com/android/base/rx/autodispose/RxLiveStateExForAutodDispose.kt rename to lib_base/src/main/java/com/android/base/rx/autodispose/RxLiveStateExForAutoDispose.kt index 1d171be..55bd5a8 100644 --- a/lib_base/src/main/java/com/android/base/rx/autodispose/RxLiveStateExForAutodDispose.kt +++ b/lib_base/src/main/java/com/android/base/rx/autodispose/RxLiveStateExForAutoDispose.kt @@ -130,109 +130,3 @@ fun CompletableSubscribeProxy.subscribeWithLiveData(liveData: MutableLiveDat } ) } - -//----------------------------------------------------------------------------------------- - -fun ObservableSubscribeProxy.toResourceLiveData(): LiveData> { - val mutableLiveData = MutableLiveData>() - mutableLiveData.value = State.loading() - subscribe( - { - mutableLiveData.postValue(State.success(it)) - }, - { - mutableLiveData.postValue(State.error(it)) - } - ) - return mutableLiveData -} - -fun ObservableSubscribeProxy>.optionalToResourceLiveData(): LiveData> { - val mutableLiveData = MutableLiveData>() - mutableLiveData.value = State.loading() - subscribe( - { - mutableLiveData.postValue(State.success(it.orElse(null))) - }, - { - mutableLiveData.postValue(State.error(it)) - } - ) - return mutableLiveData -} - -fun FlowableSubscribeProxy.toResourceLiveData(): LiveData> { - val mutableLiveData = MutableLiveData>() - mutableLiveData.value = State.loading() - subscribe( - { - mutableLiveData.postValue(State.success(it)) - }, - { - mutableLiveData.postValue(State.error(it)) - } - ) - return mutableLiveData -} - -fun FlowableSubscribeProxy>.optionalToResourceLiveData(): LiveData> { - val mutableLiveData = MutableLiveData>() - mutableLiveData.value = State.loading() - subscribe( - { - mutableLiveData.postValue(State.success(it.orElse(null))) - }, - { - mutableLiveData.postValue(State.error(it)) - } - ) - return mutableLiveData -} - -fun CompletableSubscribeProxy.toResourceLiveData(): LiveData> { - val mutableLiveData = MutableLiveData>() - mutableLiveData.value = State.loading() - subscribe( - { - mutableLiveData.postValue(State.success()) - }, - { - mutableLiveData.postValue(State.error(it)) - } - ) - return mutableLiveData -} - -//----------------------------------------------------------------------------------------- - -fun ObservableSubscribeProxy.toLiveData(): LiveData { - val liveData = MutableLiveData() - this.subscribeIgnoreError { - liveData.postValue(it) - } - return liveData -} - -fun FlowableSubscribeProxy.toLiveData(): LiveData { - val liveData = MutableLiveData() - this.subscribeIgnoreError { - liveData.postValue(it) - } - return liveData -} - -fun SingleSubscribeProxy.toLiveData(): LiveData { - val liveData = MutableLiveData() - this.subscribeIgnoreError { - liveData.postValue(it) - } - return liveData -} - -fun MaybeSubscribeProxy.toLiveData(): LiveData { - val liveData = MutableLiveData() - this.subscribeIgnoreError { - liveData.postValue(it) - } - return liveData -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/rx/autodispose/RxLivedataForAutoDispose.kt b/lib_base/src/main/java/com/android/base/rx/autodispose/RxLivedataForAutoDispose.kt new file mode 100644 index 0000000..7807605 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/rx/autodispose/RxLivedataForAutoDispose.kt @@ -0,0 +1,109 @@ +package com.android.base.rx.autodispose + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import com.android.base.data.State +import com.github.dmstocking.optional.java.util.Optional +import com.uber.autodispose.* + +fun ObservableSubscribeProxy.toResourceLiveData(): LiveData> { + val mutableLiveData = MutableLiveData>() + mutableLiveData.value = State.loading() + subscribe( + { + mutableLiveData.postValue(State.success(it)) + }, + { + mutableLiveData.postValue(State.error(it)) + } + ) + return mutableLiveData +} + +fun ObservableSubscribeProxy>.optionalToResourceLiveData(): LiveData> { + val mutableLiveData = MutableLiveData>() + mutableLiveData.value = State.loading() + subscribe( + { + mutableLiveData.postValue(State.success(it.orElse(null))) + }, + { + mutableLiveData.postValue(State.error(it)) + } + ) + return mutableLiveData +} + +fun FlowableSubscribeProxy.toResourceLiveData(): LiveData> { + val mutableLiveData = MutableLiveData>() + mutableLiveData.value = State.loading() + subscribe( + { + mutableLiveData.postValue(State.success(it)) + }, + { + mutableLiveData.postValue(State.error(it)) + } + ) + return mutableLiveData +} + +fun FlowableSubscribeProxy>.optionalToResourceLiveData(): LiveData> { + val mutableLiveData = MutableLiveData>() + mutableLiveData.value = State.loading() + subscribe( + { + mutableLiveData.postValue(State.success(it.orElse(null))) + }, + { + mutableLiveData.postValue(State.error(it)) + } + ) + return mutableLiveData +} + +fun CompletableSubscribeProxy.toResourceLiveData(): LiveData> { + val mutableLiveData = MutableLiveData>() + mutableLiveData.value = State.loading() + subscribe( + { + mutableLiveData.postValue(State.success()) + }, + { + mutableLiveData.postValue(State.error(it)) + } + ) + return mutableLiveData +} + +fun ObservableSubscribeProxy.toLiveData(): LiveData { + val liveData = MutableLiveData() + this.subscribeIgnoreError { + liveData.postValue(it) + } + return liveData +} + +fun FlowableSubscribeProxy.toLiveData(): LiveData { + val liveData = MutableLiveData() + this.subscribeIgnoreError { + liveData.postValue(it) + } + return liveData +} + +fun SingleSubscribeProxy.toLiveData(): LiveData { + val liveData = MutableLiveData() + this.subscribeIgnoreError { + liveData.postValue(it) + } + return liveData +} + +fun MaybeSubscribeProxy.toLiveData(): LiveData { + val liveData = MutableLiveData() + this.subscribeIgnoreError { + liveData.postValue(it) + } + return liveData +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/utils/android/views/TextViewEx.kt b/lib_base/src/main/java/com/android/base/utils/android/views/TextViewEx.kt index 67cbee1..f0693ce 100644 --- a/lib_base/src/main/java/com/android/base/utils/android/views/TextViewEx.kt +++ b/lib_base/src/main/java/com/android/base/utils/android/views/TextViewEx.kt @@ -123,12 +123,16 @@ fun Button.enableByEditText(et: EditText, checker: (s: CharSequence?) -> Boolean }) } -fun TextInputLayout.textString(): String { +fun TextInputLayout.textValue(): String { val editText = this.editText return editText?.text?.toString() ?: "" } -fun EditText.textString(): String { +fun EditText.textValue(): String { + return this.text?.toString() ?: "" +} + +fun TextView.textValue(): String { return this.text?.toString() ?: "" } diff --git a/lib_base/src/main/java/com/android/base/utils/upgrade/AppUpgradeChecker.kt b/lib_base/src/main/java/com/android/base/utils/upgrade/AppUpgradeChecker.kt index 955b829..bfd0be5 100644 --- a/lib_base/src/main/java/com/android/base/utils/upgrade/AppUpgradeChecker.kt +++ b/lib_base/src/main/java/com/android/base/utils/upgrade/AppUpgradeChecker.kt @@ -181,7 +181,7 @@ object AppUpgradeChecker { } private fun safeContext(onContext: (Activity) -> Unit) { - val topActivity = Sword.get().topActivity + val topActivity = Sword.topActivity if (topActivity != null) { onContext(topActivity) } else { @@ -189,7 +189,7 @@ object AppUpgradeChecker { override fun onBackground() = Unit override fun onForeground() { AppUtils.unregisterAppStatusChangedListener(this) - Sword.get().topActivity?.let { onContext(it) } + Sword.topActivity?.let { onContext(it) } } }) } diff --git a/lib_base/src/main/java/com/android/base/widget/viewpager/BannerPagerAdapter.java b/lib_base/src/main/java/com/android/base/widget/viewpager/BannerPagerAdapter.java index 72acb19..264af36 100644 --- a/lib_base/src/main/java/com/android/base/widget/viewpager/BannerPagerAdapter.java +++ b/lib_base/src/main/java/com/android/base/widget/viewpager/BannerPagerAdapter.java @@ -56,11 +56,15 @@ public abstract class BannerPagerAdapter extends PagerAdapter { setTransitionName(imageView); callImageClicked(position, imageView); String url = mEntities.get(position); - ImageLoaderFactory.getImageLoader().display(imageView, url); + displayImage(imageView, url); container.addView(imageView, 0); return imageView; } + protected void displayImage(@NonNull ImageView imageView, @NonNull String url) { + ImageLoaderFactory.getImageLoader().display(imageView, url); + } + protected final void callImageClicked(int position, ImageView imageView) { if (mClickListener != null) { mClickListener.onClick(imageView, mIsLooper ? position - 1 : position); diff --git a/lib_base/src/test/java/com/android/base/rx/RxBusTest.java b/lib_base/src/test/java/com/android/base/rx/RxBusTest.java index 8676648..1b4a87c 100644 --- a/lib_base/src/test/java/com/android/base/rx/RxBusTest.java +++ b/lib_base/src/test/java/com/android/base/rx/RxBusTest.java @@ -1,5 +1,6 @@ package com.android.base.rx; +import org.jetbrains.annotations.NotNull; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -21,18 +22,17 @@ public class RxBusTest { private C mC1; private static class A { + final String name; private A(String name) { this.name = "A " + name; } + @NotNull @Override public String toString() { - return "A{" + - "name='" + name + '\'' + - '}'; - } + return "A{" + "name='" + name + '\'' + '}'; } } private static class C extends A { @@ -40,11 +40,10 @@ public class RxBusTest { super(name); } + @NotNull @Override public String toString() { - return "C {" + - "name='" + name + '\'' + - '}'; + return "C {" + "name='" + name + '\'' + '}'; } } @@ -55,11 +54,10 @@ public class RxBusTest { this.name = "B " + name; } + @NotNull @Override public String toString() { - return "B{" + - "name='" + name + '\'' + - '}'; + return "B{" + "name='" + name + '\'' + '}'; } } @@ -102,7 +100,7 @@ public class RxBusTest { } @Test - public void send() throws Exception { + public void send() { A a = new A("A01"); mRxBus.send(a); Assert.assertSame(a, mA); @@ -113,7 +111,6 @@ public class RxBusTest { Assert.assertNotSame(b, mB); Assert.assertSame(b, mB1); - C c = new C("C01"); mRxBus.send("C", c); Assert.assertNotSame(c, mC); @@ -121,7 +118,6 @@ public class RxBusTest { mRxBus.send("A", c); mRxBus.send(c); - } } \ No newline at end of file diff --git a/lib_base/src/test/java/com/android/base/rx/TestApplication.java b/lib_base/src/test/java/com/android/base/rx/TestApplication.java deleted file mode 100644 index f627f89..0000000 --- a/lib_base/src/test/java/com/android/base/rx/TestApplication.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.android.base.rx; - -import android.app.Application; -import android.content.Context; - -import com.android.base.app.Sword; - -/** - * @author Ztiany - * Email: ztiany3@gmail.com - * Date : 2018-11-28 17:50 - */ -public class TestApplication extends Application { - - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(base); - Sword.get().getApplicationDelegate().attachBaseContext(base); - } - -} diff --git a/lib_base/src/test/java/com/android/base/rx/TestBaseActivity.java b/lib_base/src/test/java/com/android/base/rx/TestBaseActivity.java deleted file mode 100644 index 9def28c..0000000 --- a/lib_base/src/test/java/com/android/base/rx/TestBaseActivity.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.android.base.rx; - -import android.os.Bundle; -import android.support.annotation.Nullable; - -import com.android.base.app.activity.BaseActivity; - -/** - * @author Ztiany - * Email: 1169654504@qq.com - * Date : 2017-06-22 09:37 - */ -public class TestBaseActivity extends BaseActivity { - - @Override - protected void initialize(@Nullable Bundle savedInstanceState) { - super.initialize(savedInstanceState); - } - - @Override - protected Object layout() { - return 0; - } - - @Override - protected void setupView(@Nullable Bundle savedInstanceState) { - } - -} \ No newline at end of file diff --git a/lib_base/src/test/java/com/android/base/rx/TestListFragment.java b/lib_base/src/test/java/com/android/base/rx/TestListFragment.java deleted file mode 100644 index 71f1e45..0000000 --- a/lib_base/src/test/java/com/android/base/rx/TestListFragment.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.android.base.rx; - -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.android.base.adapter.recycler.MultiTypeAdapter; -import com.android.base.app.fragment.BaseListFragment; -import com.android.base.app.ui.AutoPageNumber; - -import org.jetbrains.annotations.NotNull; - -/** - * @author Ztiany - * Email: ztiany3@gmail.com - * Date : 2018-04-27 15:05 - */ -public class TestListFragment extends BaseListFragment { - - @Override - protected void onViewPrepared(@NotNull @NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewPrepared(view, savedInstanceState); - MultiTypeAdapter recyclerAdapter = new MultiTypeAdapter(getContext()); - setupLoadMore(recyclerAdapter, new AutoPageNumber(this,recyclerAdapter)); - } - -} diff --git a/lib_base/src/test/java/com/android/base/rx/TestStateFragment.java b/lib_base/src/test/java/com/android/base/rx/TestStateFragment.java deleted file mode 100644 index 41d5d3c..0000000 --- a/lib_base/src/test/java/com/android/base/rx/TestStateFragment.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.android.base.rx; - -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.view.View; - -import com.android.base.app.fragment.BaseStateFragment; - -import org.jetbrains.annotations.NotNull; - -/** - * @author Ztiany - * Email: 1169654504@qq.com - * Date : 2017-06-22 09:38 - */ -public class TestStateFragment extends BaseStateFragment { - - @Override - public void onAttach(@NotNull Context context) { - super.onAttach(context); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - } - - @Override - protected void onViewPrepared(@NotNull @NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewPrepared(view, savedInstanceState); - getStateLayoutConfig(); - } - - @Override - protected void onRefresh() { - super.onRefresh(); - } - - @Override - public void refreshCompleted() { - super.refreshCompleted(); - } - -}