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 new file mode 100644 index 0000000..f887a19 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/InjectorBaseAppContext.kt @@ -0,0 +1,18 @@ +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 index a144d95..01f82a9 100644 --- a/lib_base/src/main/java/com/android/base/app/Sword.java +++ b/lib_base/src/main/java/com/android/base/app/Sword.java @@ -6,9 +6,9 @@ import android.content.Context; import android.os.Bundle; import com.android.base.app.dagger.Injectable; -import com.android.base.app.fragment.FragmentAnimator; -import com.android.base.app.fragment.FragmentConfig; -import com.android.base.app.fragment.LoadingViewFactory; +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; diff --git a/lib_base/src/main/java/com/android/base/app/activity/ActivityDelegateOwner.java b/lib_base/src/main/java/com/android/base/app/activity/ActivityDelegateOwner.java index 831932b..622b3ef 100644 --- a/lib_base/src/main/java/com/android/base/app/activity/ActivityDelegateOwner.java +++ b/lib_base/src/main/java/com/android/base/app/activity/ActivityDelegateOwner.java @@ -15,6 +15,6 @@ public interface ActivityDelegateOwner { ActivityDelegate findDelegate(Predicate predicate); - ActivityStatus getStatus(); + ActivityState getStatus(); } diff --git a/lib_base/src/main/java/com/android/base/app/activity/ActivityStatus.kt b/lib_base/src/main/java/com/android/base/app/activity/ActivityState.kt similarity index 81% rename from lib_base/src/main/java/com/android/base/app/activity/ActivityStatus.kt rename to lib_base/src/main/java/com/android/base/app/activity/ActivityState.kt index e0fd32a..6f69297 100644 --- a/lib_base/src/main/java/com/android/base/app/activity/ActivityStatus.kt +++ b/lib_base/src/main/java/com/android/base/app/activity/ActivityState.kt @@ -1,6 +1,6 @@ package com.android.base.app.activity -enum class ActivityStatus { +enum class ActivityState { INITIALIZED, CREATE, START, diff --git a/lib_base/src/main/java/com/android/base/app/activity/BackHandlerHelper.java b/lib_base/src/main/java/com/android/base/app/activity/BackHandlerHelper.java index 52f474e..5180d54 100644 --- a/lib_base/src/main/java/com/android/base/app/activity/BackHandlerHelper.java +++ b/lib_base/src/main/java/com/android/base/app/activity/BackHandlerHelper.java @@ -13,6 +13,7 @@ import androidx.fragment.app.FragmentManager; * 3.在Fragment中嵌套使用Fragment时,请使用getSupportChildFragmentManager * */ +@SuppressWarnings("WeakerAccess") public class BackHandlerHelper { /** diff --git a/lib_base/src/main/java/com/android/base/app/activity/BaseActivity.java b/lib_base/src/main/java/com/android/base/app/activity/BaseActivity.java deleted file mode 100644 index c4ff5d0..0000000 --- a/lib_base/src/main/java/com/android/base/app/activity/BaseActivity.java +++ /dev/null @@ -1,224 +0,0 @@ -package com.android.base.app.activity; - -import android.content.Intent; -import android.os.Bundle; -import android.view.View; - -import com.android.base.utils.android.compat.AndroidVersion; -import com.github.dmstocking.optional.java.util.function.Predicate; - -import org.jetbrains.annotations.NotNull; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.UiThread; -import androidx.appcompat.app.AppCompatActivity; -import timber.log.Timber; - -/** - *
- *          1,封装通用流程。
- *          2,onBackPressed 事件分发,优先交给 Fragment 处理。
- *          3,提供 RxJava 的生命周期绑定。
- *  
- * - * @author Ztiany - * Date : 2016-05-04 15:40 - * Email: 1169654504@qq.com - */ -public abstract class BaseActivity extends AppCompatActivity implements ActivityDelegateOwner { - - private final ActivityDelegates mActivityDelegates = new ActivityDelegates(this); - - private ActivityStatus mActivityStatus = ActivityStatus.INITIALIZED; - - private String tag() { - return this.getClass().getSimpleName(); - } - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - Timber.tag(tag()).d("---->onCreate before call super"); - - initialize(savedInstanceState); - mActivityDelegates.callOnCreateBeforeSetContentView(savedInstanceState); - - super.onCreate(savedInstanceState); - Timber.tag(tag()).d("---->onCreate after call super " + "bundle = " + savedInstanceState); - - Object layout = layout(); - if (layout instanceof View) { - setContentView((View) layout); - } else if (layout instanceof Integer) { - setContentView((Integer) layout); - } else if (layout == null) { - Timber.d("layout() return null layout"); - } else { - throw new IllegalArgumentException("layout() return type no support, layout = " + layout); - } - - mActivityStatus = ActivityStatus.CREATE; - mActivityDelegates.callOnCreateAfterSetContentView(savedInstanceState); - - setupView(savedInstanceState); - } - - @Override - protected void onRestart() { - Timber.tag(tag()).d("---->onRestart before call super"); - super.onRestart(); - Timber.tag(tag()).d("---->onRestart after call super "); - mActivityDelegates.callOnRestart(); - } - - @Override - protected void onStart() { - Timber.tag(tag()).d("---->onStart before call super"); - super.onStart(); - Timber.tag(tag()).d("---->onStart after call super"); - mActivityStatus = ActivityStatus.START; - mActivityDelegates.callOnStart(); - } - - @Override - protected void onResume() { - Timber.tag(tag()).d("---->onResume before call super"); - super.onResume(); - Timber.tag(tag()).d("---->onResume after call super"); - mActivityStatus = ActivityStatus.RESUME; - mActivityDelegates.callOnResume(); - } - - @Override - protected void onPause() { - Timber.tag(tag()).d("---->onPause before call super"); - mActivityStatus = ActivityStatus.PAUSE; - mActivityDelegates.callOnPause(); - super.onPause(); - Timber.tag(tag()).d("---->onPause after call super "); - } - - @Override - protected void onStop() { - Timber.tag(tag()).d("---->onStop before call super"); - mActivityStatus = ActivityStatus.STOP; - mActivityDelegates.callOnStop(); - super.onStop(); - Timber.tag(tag()).d("---->onStop after call super"); - } - - @Override - protected void onDestroy() { - Timber.tag(tag()).d("---->onDestroy before call super"); - mActivityStatus = ActivityStatus.DESTROY; - mActivityDelegates.callOnDestroy(); - super.onDestroy(); - Timber.tag(tag()).d("---->onDestroy after call super"); - } - - @Override - protected void onPostCreate(@Nullable Bundle savedInstanceState) { - super.onPostCreate(savedInstanceState); - mActivityDelegates.callOnPostCreate(savedInstanceState); - } - - @Override - protected void onSaveInstanceState(@NotNull Bundle outState) { - super.onSaveInstanceState(outState); - mActivityDelegates.callOnSaveInstanceState(outState); - } - - @Override - protected void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - mActivityDelegates.callOnRestoreInstanceState(savedInstanceState); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - mActivityDelegates.callOnActivityResult(requestCode, resultCode, data); - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - mActivityDelegates.callOnRequestPermissionsResult(requestCode, permissions, grantResults); - } - - @Override - protected void onResumeFragments() { - super.onResumeFragments(); - mActivityDelegates.callOnResumeFragments(); - } - - /////////////////////////////////////////////////////////////////////////// - // interface impl - /////////////////////////////////////////////////////////////////////////// - @UiThread - @Override - public final void addDelegate(@NonNull ActivityDelegate activityDelegate) { - mActivityDelegates.addActivityDelegate(activityDelegate); - } - - @SuppressWarnings("unused") - @UiThread - @Override - public final boolean removeDelegate(@NonNull ActivityDelegate activityDelegate) { - return mActivityDelegates.removeActivityDelegate(activityDelegate); - } - - @Override - public ActivityDelegate findDelegate(Predicate predicate) { - return mActivityDelegates.findDelegate(predicate); - } - - @Override - public ActivityStatus getStatus() { - return mActivityStatus; - } - - /** - * Before call super.onCreate and setContentView - * - * @param savedInstanceState state - */ - protected void initialize(@Nullable Bundle savedInstanceState) { - } - - /** - * provide a layoutId (int) or layout (View) - * - * @return layoutId - */ - @Nullable - protected abstract Object layout(); - - /** - * after setContentView - */ - protected abstract void setupView(@Nullable Bundle savedInstanceState); - - @Override - public void onBackPressed() { - if (BackHandlerHelper.handleBackPress(this)) { - Timber.d("onBackPressed() called but child fragment handle it"); - } else { - superOnBackPressed(); - } - } - - protected void superOnBackPressed() { - super.onBackPressed(); - } - - @Override - public boolean isDestroyed() { - if (AndroidVersion.atLeast(17)) { - return super.isDestroyed(); - } else { - return getStatus() == ActivityStatus.DESTROY; - } - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/activity/BaseActivity.kt b/lib_base/src/main/java/com/android/base/app/activity/BaseActivity.kt new file mode 100644 index 0000000..5b8dbf8 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/activity/BaseActivity.kt @@ -0,0 +1,190 @@ +package com.android.base.app.activity + +import android.content.Intent +import android.os.Bundle +import android.view.View +import androidx.annotation.UiThread +import androidx.appcompat.app.AppCompatActivity +import androidx.fragment.app.Fragment +import com.android.base.rx.AutoDisposeLifecycleOwnerEx +import com.android.base.utils.android.compat.AndroidVersion +import com.github.dmstocking.optional.java.util.function.Predicate +import timber.log.Timber + +/** + * 基础 BaseActivity 封装: + * + * 1. 封装通用流程。 + * 2. [onBackPressed] 事件分发,优先交给 [Fragment] 处理。 + * 3. 提供 RxJava 的生命周期绑定。 + * + * @author Ztiany + * Date : 2016-05-04 15:40 + * Email: 1169654504@qq.com + */ +abstract class BaseActivity : AppCompatActivity(), ActivityDelegateOwner, AutoDisposeLifecycleOwnerEx { + + @Suppress("LeakingThis") + private val activityDelegates = ActivityDelegates(this) + + private var activityState = ActivityState.INITIALIZED + + private fun tag() = this.javaClass.simpleName + + override fun onCreate(savedInstanceState: Bundle?) { + Timber.tag(tag()).d("---->onCreate before call super") + initialize(savedInstanceState) + activityDelegates.callOnCreateBeforeSetContentView(savedInstanceState) + super.onCreate(savedInstanceState) + Timber.tag(tag()).d("---->onCreate after call super bundle = $savedInstanceState") + + when (val layout = layout()) { + is View -> setContentView(layout) + is Int -> setContentView(layout) + null -> Timber.d("layout() return null layout") + else -> throw IllegalArgumentException("layout() return type no support, layout = $layout") + } + + activityState = ActivityState.CREATE + activityDelegates.callOnCreateAfterSetContentView(savedInstanceState) + setupView(savedInstanceState) + } + + override fun onRestart() { + Timber.tag(tag()).d("---->onRestart before call super") + super.onRestart() + Timber.tag(tag()).d("---->onRestart after call super ") + activityDelegates.callOnRestart() + } + + override fun onStart() { + Timber.tag(tag()).d("---->onStart before call super") + super.onStart() + Timber.tag(tag()).d("---->onStart after call super") + activityState = ActivityState.START + activityDelegates.callOnStart() + } + + override fun onResume() { + Timber.tag(tag()).d("---->onResume before call super") + super.onResume() + Timber.tag(tag()).d("---->onResume after call super") + activityState = ActivityState.RESUME + activityDelegates.callOnResume() + } + + override fun onPause() { + Timber.tag(tag()).d("---->onPause before call super") + activityState = ActivityState.PAUSE + activityDelegates.callOnPause() + super.onPause() + Timber.tag(tag()).d("---->onPause after call super ") + } + + override fun onStop() { + Timber.tag(tag()).d("---->onStop before call super") + activityState = ActivityState.STOP + activityDelegates.callOnStop() + super.onStop() + Timber.tag(tag()).d("---->onStop after call super") + } + + override fun onDestroy() { + Timber.tag(tag()).d("---->onDestroy before call super") + activityState = ActivityState.DESTROY + activityDelegates.callOnDestroy() + super.onDestroy() + Timber.tag(tag()).d("---->onDestroy after call super") + } + + override fun onPostCreate(savedInstanceState: Bundle?) { + super.onPostCreate(savedInstanceState) + activityDelegates.callOnPostCreate(savedInstanceState) + } + + override fun onSaveInstanceState(outState: Bundle) { + super.onSaveInstanceState(outState) + activityDelegates.callOnSaveInstanceState(outState) + } + + override fun onRestoreInstanceState(savedInstanceState: Bundle) { + super.onRestoreInstanceState(savedInstanceState) + activityDelegates.callOnRestoreInstanceState(savedInstanceState) + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + activityDelegates.callOnActivityResult(requestCode, resultCode, data) + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + activityDelegates.callOnRequestPermissionsResult(requestCode, permissions, grantResults) + } + + override fun onResumeFragments() { + super.onResumeFragments() + activityDelegates.callOnResumeFragments() + } + + /////////////////////////////////////////////////////////////////////////// + // interface impl + /////////////////////////////////////////////////////////////////////////// + @UiThread + override fun addDelegate(activityDelegate: ActivityDelegate<*>) { + activityDelegates.addActivityDelegate(activityDelegate) + } + + @UiThread + override fun removeDelegate(activityDelegate: ActivityDelegate<*>): Boolean { + return activityDelegates.removeActivityDelegate(activityDelegate) + } + + override fun findDelegate(predicate: Predicate?>?): ActivityDelegate<*>? { + return activityDelegates.findDelegate(predicate) + } + + override fun getStatus(): ActivityState { + return activityState + } + + /** + * Before call super.onCreate and setContentView + * + * @param savedInstanceState state + */ + protected open fun initialize(savedInstanceState: Bundle?) {} + + /** + * provide a layoutId (int) or layout (View) + * + * @return layoutId + */ + protected abstract fun layout(): Any? + + /** + * after setContentView + */ + protected abstract fun setupView(savedInstanceState: Bundle?) + + override fun onBackPressed() { + if (BackHandlerHelper.handleBackPress(this)) { + Timber.d("onBackPressed() called but child fragment handle it") + } else { + superOnBackPressed() + } + } + + protected open fun superOnBackPressed() { + super.onBackPressed() + } + + override fun isDestroyed(): Boolean { + return if (AndroidVersion.atLeast(17)) { + super.isDestroyed() + } else { + status === ActivityState.DESTROY + } + } + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/activity/InjectorBaseActivity.java b/lib_base/src/main/java/com/android/base/app/activity/InjectorBaseActivity.java new file mode 100644 index 0000000..95e01a0 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/activity/InjectorBaseActivity.java @@ -0,0 +1,26 @@ +package com.android.base.app.activity; + +import com.android.base.app.dagger.Injectable; + +import javax.inject.Inject; + +import dagger.android.AndroidInjector; +import dagger.android.DispatchingAndroidInjector; +import dagger.android.HasAndroidInjector; + +/** + * @author Ztiany + * Email: 1169654504@qq.com + * Date : 2018-11-01 + */ +public abstract class InjectorBaseActivity extends BaseActivity implements Injectable, HasAndroidInjector { + + @Inject + DispatchingAndroidInjector androidInjector; + + @Override + public AndroidInjector androidInjector() { + return androidInjector; + } + +} diff --git a/lib_base/src/main/java/com/android/base/app/fragment/BaseDialogFragment.java b/lib_base/src/main/java/com/android/base/app/fragment/BaseDialogFragment.java deleted file mode 100644 index efbc09f..0000000 --- a/lib_base/src/main/java/com/android/base/app/fragment/BaseDialogFragment.java +++ /dev/null @@ -1,280 +0,0 @@ -package com.android.base.app.fragment; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.android.base.app.Sword; -import com.android.base.app.activity.BackHandlerHelper; -import com.android.base.app.activity.OnBackPressListener; -import com.android.base.app.ui.LoadingView; -import com.github.dmstocking.optional.java.util.function.Predicate; - -import org.jetbrains.annotations.NotNull; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.annotation.StringRes; -import androidx.annotation.UiThread; -import androidx.appcompat.app.AppCompatDialogFragment; -import timber.log.Timber; - -/** - * 提供: - *
- *     1. RxJava 生命周期绑定。
- *     2. 返回键监听。
- *     3. 显示 LoadingDialog 和 Message。
- *     4. 可以添加生命周期代理。
- * 
- * - * @author Ztiany - * date : 2016-03-19 23:09 - * email: 1169654504@qq.com - */ -public class BaseDialogFragment extends AppCompatDialogFragment implements LoadingView, OnBackPressListener, FragmentDelegateOwner { - - private LoadingView mLoadingViewImpl; - - private View mLayoutView; - - /* just for cache*/ - private View mCachedView; - - private final FragmentDelegates mFragmentDelegates = new FragmentDelegates(this); - - private String tag() { - return this.getClass().getSimpleName(); - } - - @Override - public void onAttach(@NotNull Context context) { - super.onAttach(context); - Timber.tag(tag()).d("onAttach() called with: context = [" + context + "]"); - mFragmentDelegates.onAttach(context); - } - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Timber.tag(tag()).d("-->onCreate savedInstanceState = " + savedInstanceState); - mFragmentDelegates.onCreate(savedInstanceState); - } - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - if (mCachedView == null) { - Object layout = provideLayout(); - if (layout == null) { - return null; - } - if (layout instanceof Integer) { - return mCachedView = inflater.inflate((Integer) layout, container, false); - } - if (layout instanceof View) { - return mCachedView = (View) layout; - } - throw new IllegalArgumentException("Here you should provide a layout id or a View"); - } - return mCachedView; - } - - /** - * 使用此方法提供的布局,将只会被缓存起来,即此方法将只会被调用一次。 - * - * @return provide a layout id or a View - */ - @Nullable - @SuppressWarnings("unused") - protected Object provideLayout() { - return null; - } - - @Override - public final void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - Timber.tag(tag()).d("-->onViewCreated savedInstanceState = " + savedInstanceState); - if (mLayoutView != view) { - mLayoutView = view; - internalOnViewPrepared(view, savedInstanceState); - onViewPrepared(view, savedInstanceState); - } - mFragmentDelegates.onViewCreated(view, savedInstanceState); - } - - void internalOnViewPrepared(@NonNull View view, @Nullable Bundle savedInstanceState) { - } - - /** - * View is prepared, If {@link androidx.fragment.app.Fragment#onCreateView(LayoutInflater, ViewGroup, Bundle)} return same layout, it will be called once - * - * @param view view of fragment - */ - protected void onViewPrepared(@NonNull View view, @Nullable Bundle savedInstanceState) { - } - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - Timber.tag(tag()).d("-->onActivityCreated savedInstanceState = " + savedInstanceState); - mFragmentDelegates.onActivityCreated(savedInstanceState); - } - - @Override - public void onStart() { - super.onStart(); - Timber.tag(tag()).d("-->onStart"); - mFragmentDelegates.onStart(); - } - - @Override - public void onResume() { - super.onResume(); - Timber.tag(tag()).d("-->onResume"); - mFragmentDelegates.onResume(); - } - - @Override - public void onPause() { - Timber.tag(tag()).d("-->onPause"); - mFragmentDelegates.onPause(); - super.onPause(); - } - - @Override - public void onStop() { - Timber.tag(tag()).d("-->onStop"); - mFragmentDelegates.onStop(); - super.onStop(); - } - - @Override - public void onDestroyView() { - Timber.tag(tag()).d("-->onDestroyView"); - mFragmentDelegates.onDestroyView(); - super.onDestroyView(); - } - - @Override - public void onDestroy() { - Timber.tag(tag()).d("-->onDestroy"); - mFragmentDelegates.onDestroy(); - super.onDestroy(); - dismissLoadingDialog(); - } - - @Override - public void onDetach() { - Timber.tag(tag()).d("-->onDetach"); - mFragmentDelegates.onDetach(); - super.onDetach(); - } - - @Override - public void onSaveInstanceState(@NonNull Bundle outState) { - mFragmentDelegates.onSaveInstanceState(outState); - super.onSaveInstanceState(outState); - } - - @Override - public void setUserVisibleHint(boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); - Timber.tag(tag()).d("-->setUserVisibleHint ==" + isVisibleToUser); - mFragmentDelegates.setUserVisibleHint(isVisibleToUser); - } - - @Override - public void onHiddenChanged(boolean hidden) { - super.onHiddenChanged(hidden); - Timber.tag(tag()).d("-->onHiddenChanged = " + hidden); - mFragmentDelegates.onHiddenChanged(hidden); - } - - @Override - public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults); - mFragmentDelegates.onRequestPermissionsResult(requestCode, permissions, grantResults); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - super.onActivityResult(requestCode, resultCode, data); - mFragmentDelegates.onActivityResult(requestCode, resultCode, data); - } - - @Override - @UiThread - public final void addDelegate(FragmentDelegate fragmentDelegate) { - mFragmentDelegates.addDelegate(fragmentDelegate); - } - - @Override - @UiThread - public final boolean removeDelegate(FragmentDelegate fragmentDelegate) { - return mFragmentDelegates.removeDelegate(fragmentDelegate); - } - - @Override - public FragmentDelegate findDelegate(Predicate predicate) { - return mFragmentDelegates.findDelegate(predicate); - } - - @Override - public boolean onBackPressed() { - return handleBackPress() || BackHandlerHelper.handleBackPress(this); - } - - /** - * Fragment需要自己处理BackPress事件,如果不处理,就交给子Fragment处理。都不处理则由Activity处理 - */ - protected boolean handleBackPress() { - return false; - } - - private LoadingView getLoadingViewImpl() { - if (mLoadingViewImpl == null) { - mLoadingViewImpl = Sword.get().getLoadingViewFactory().createLoadingDelegate(getContext()); - } - return mLoadingViewImpl; - } - - @Override - public void showLoadingDialog() { - getLoadingViewImpl().showLoadingDialog(true); - } - - @Override - public void showLoadingDialog(boolean cancelable) { - getLoadingViewImpl().showLoadingDialog(cancelable); - } - - @Override - public void showLoadingDialog(CharSequence message, boolean cancelable) { - getLoadingViewImpl().showLoadingDialog(message, cancelable); - } - - @Override - public void showLoadingDialog(@StringRes int messageId, boolean cancelable) { - getLoadingViewImpl().showLoadingDialog(messageId, cancelable); - } - - @Override - public void dismissLoadingDialog() { - getLoadingViewImpl().dismissLoadingDialog(); - } - - @Override - public void showMessage(CharSequence message) { - getLoadingViewImpl().showMessage(message); - } - - @Override - public void showMessage(@StringRes int messageId) { - getLoadingViewImpl().showMessage(messageId); - } - -} \ 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 new file mode 100644 index 0000000..49e6864 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/BaseDialogFragment.kt @@ -0,0 +1,250 @@ +package com.android.base.app.fragment + +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.annotation.StringRes +import androidx.annotation.UiThread +import androidx.appcompat.app.AppCompatDialogFragment +import com.android.base.app.Sword +import com.android.base.app.activity.BackHandlerHelper +import com.android.base.app.activity.OnBackPressListener +import com.android.base.app.fragment.delegates.FragmentDelegate +import com.android.base.app.fragment.delegates.FragmentDelegateOwner +import com.android.base.app.ui.LoadingView +import com.android.base.rx.AutoDisposeLifecycleOwnerEx +import com.github.dmstocking.optional.java.util.function.Predicate +import timber.log.Timber + +/** + * @author Ztiany + * date : 2016-03-19 23:09 + * email: 1169654504@qq.com + * @see [BaseFragment] + */ +open class BaseDialogFragment : AppCompatDialogFragment(), LoadingView, OnBackPressListener, FragmentDelegateOwner, AutoDisposeLifecycleOwnerEx { + + private var loadingView: LoadingView? = null + + private var layoutView: View? = null + + /** just for cache*/ + private var cachedView: View? = null + + @Suppress("LeakingThis") + private val fragmentDelegates = FragmentDelegates(this) + + private fun tag() = this.javaClass.simpleName + + override fun onAttach(context: Context) { + super.onAttach(context) + Timber.tag(tag()).d("onAttach() called with: context = [$context]") + fragmentDelegates.onAttach(context) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + Timber.tag(tag()).d("-->onCreate savedInstanceState = $savedInstanceState") + fragmentDelegates.onCreate(savedInstanceState) + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + if (cachedView == null) { + val layout = provideLayout() ?: return null + if (layout is Int) { + return inflater.inflate(layout, container, false).also { cachedView = it } + } + if (layout is View) { + cachedView = layout + return layout + } + throw IllegalArgumentException("Here you should provide a layout id or a View") + } + + Timber.tag(tag()).d("mCachedView.parent: " + cachedView?.parent) + + cachedView?.run { + val viewParent = parent + if (viewParent != null && viewParent is ViewGroup) { + viewParent.removeView(this) + } + } + + return cachedView + } + + /** + * 使用此方法提供的布局,将只会被缓存起来,即此方法将只会被调用一次。 + * + * @return provide a layout id or a View + */ + protected open fun provideLayout(): Any? = null + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + Timber.tag(tag()).d("-->onViewCreated savedInstanceState = %s", savedInstanceState) + if (layoutView !== view) { + layoutView = view + internalOnViewPrepared(view, savedInstanceState) + onViewPrepared(view, savedInstanceState) + } + fragmentDelegates.onViewCreated(view, savedInstanceState) + } + + internal open fun internalOnViewPrepared(view: View, savedInstanceState: Bundle?) {} + + /** + * View is prepared, If [androidx.fragment.app.Fragment.onCreateView] return same layout, it will be called once + * + * @param view view of fragment + */ + protected open fun onViewPrepared(view: View, savedInstanceState: Bundle?) {} + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + Timber.tag(tag()).d("-->onActivityCreated savedInstanceState = $savedInstanceState") + fragmentDelegates.onActivityCreated(savedInstanceState) + } + + override fun onStart() { + super.onStart() + Timber.tag(tag()).d("-->onStart") + fragmentDelegates.onStart() + } + + override fun onResume() { + super.onResume() + Timber.tag(tag()).d("-->onResume") + fragmentDelegates.onResume() + } + + override fun onPause() { + Timber.tag(tag()).d("-->onPause") + fragmentDelegates.onPause() + super.onPause() + } + + override fun onStop() { + Timber.tag(tag()).d("-->onStop") + fragmentDelegates.onStop() + super.onStop() + } + + override fun onDestroyView() { + Timber.tag(tag()).d("-->onDestroyView") + fragmentDelegates.onDestroyView() + super.onDestroyView() + } + + override fun onDestroy() { + Timber.tag(tag()).d("-->onDestroy") + fragmentDelegates.onDestroy() + super.onDestroy() + dismissLoadingDialog() + } + + override fun onDetach() { + Timber.tag(tag()).d("-->onDetach") + fragmentDelegates.onDetach() + super.onDetach() + } + + override fun onSaveInstanceState(outState: Bundle) { + fragmentDelegates.onSaveInstanceState(outState) + super.onSaveInstanceState(outState) + } + + override fun setUserVisibleHint(isVisibleToUser: Boolean) { + super.setUserVisibleHint(isVisibleToUser) + Timber.tag(tag()).d("-->setUserVisibleHint ==$isVisibleToUser") + fragmentDelegates.setUserVisibleHint(isVisibleToUser) + } + + override fun onHiddenChanged(hidden: Boolean) { + super.onHiddenChanged(hidden) + Timber.tag(tag()).d("-->onHiddenChanged = $hidden") + fragmentDelegates.onHiddenChanged(hidden) + } + + override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults) + fragmentDelegates.onRequestPermissionsResult(requestCode, permissions, grantResults) + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + fragmentDelegates.onActivityResult(requestCode, resultCode, data) + } + + @UiThread + override fun addDelegate(fragmentDelegate: FragmentDelegate<*>?) { + fragmentDelegates.addDelegate(fragmentDelegate) + } + + @UiThread + override fun removeDelegate(fragmentDelegate: FragmentDelegate<*>?): Boolean { + return fragmentDelegates.removeDelegate(fragmentDelegate) + } + + override fun findDelegate(predicate: Predicate?>?): FragmentDelegate<*>? { + return fragmentDelegates.findDelegate(predicate) + } + + final override fun onBackPressed(): Boolean { + return handleBackPress() || BackHandlerHelper.handleBackPress(this) + } + + /** + * Fragment需要自己处理BackPress事件,如果不处理,就交给子Fragment处理。都不处理则由Activity处理 + */ + protected open fun handleBackPress(): Boolean { + return false + } + + private fun loadingView(): LoadingView? { + val loadingViewImpl = loadingView + if (loadingViewImpl == null) { + loadingView = onCreateLoadingView() + } + if (loadingViewImpl == null) { + loadingView = Sword.get().loadingViewFactory.createLoadingDelegate(requireContext()) + } + return loadingViewImpl + } + + protected open fun onCreateLoadingView(): LoadingView? { + return null + } + + override fun showLoadingDialog() { + loadingView()?.showLoadingDialog(true) + } + + override fun showLoadingDialog(cancelable: Boolean) { + loadingView()?.showLoadingDialog(cancelable) + } + + override fun showLoadingDialog(message: CharSequence, cancelable: Boolean) { + loadingView()?.showLoadingDialog(message, cancelable) + } + + override fun showLoadingDialog(@StringRes messageId: Int, cancelable: Boolean) { + loadingView()?.showLoadingDialog(messageId, cancelable) + } + + override fun dismissLoadingDialog() { + loadingView()?.dismissLoadingDialog() + } + + override fun showMessage(message: CharSequence) { + loadingView()?.showMessage(message) + } + + override fun showMessage(@StringRes messageId: Int) { + loadingView()?.showMessage(messageId) + } + +} \ No newline at end of file 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 0fbf4d3..d28fa79 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 @@ -13,7 +13,12 @@ import androidx.fragment.app.Fragment import com.android.base.app.Sword import com.android.base.app.activity.BackHandlerHelper import com.android.base.app.activity.OnBackPressListener +import com.android.base.app.fragment.animator.FragmentAnimatorHelper +import com.android.base.app.fragment.delegates.FragmentDelegate +import com.android.base.app.fragment.delegates.FragmentDelegateOwner +import com.android.base.app.fragment.tools.FragmentConfig import com.android.base.app.ui.LoadingView +import com.android.base.rx.AutoDisposeLifecycleOwnerEx import com.github.dmstocking.optional.java.util.function.Predicate import timber.log.Timber @@ -29,7 +34,7 @@ import timber.log.Timber * date : 2016-03-19 23:09 * email: 1169654504@qq.com */ -open class BaseFragment : Fragment(), LoadingView, OnBackPressListener, FragmentDelegateOwner { +open class BaseFragment : Fragment(), LoadingView, OnBackPressListener, FragmentDelegateOwner, AutoDisposeLifecycleOwnerEx { private var loadingView: LoadingView? = null @@ -216,7 +221,7 @@ open class BaseFragment : Fragment(), LoadingView, OnBackPressListener, Fragment loadingView = onCreateLoadingView() } if (loadingViewImpl == null) { - loadingView = Sword.get().loadingViewFactory.createLoadingDelegate(context) + loadingView = Sword.get().loadingViewFactory.createLoadingDelegate(requireContext()) } return loadingViewImpl } @@ -255,9 +260,9 @@ open class BaseFragment : Fragment(), LoadingView, OnBackPressListener, Fragment override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? { if (fragmentAnimatorHelper == null) { - fragmentAnimatorHelper = FragmentAnimatorHelper(context, FragmentConfig.defaultFragmentAnimator()) + fragmentAnimatorHelper = FragmentAnimatorHelper(requireContext(), FragmentConfig.defaultFragmentAnimator()) } - return fragmentAnimatorHelper!!.onCreateAnimation(transit, enter) + return fragmentAnimatorHelper?.onCreateAnimation(transit, enter) } } \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/BaseListDialogFragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/BaseListDialogFragment.kt new file mode 100644 index 0000000..fb4bb1f --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/BaseListDialogFragment.kt @@ -0,0 +1,89 @@ +package com.android.base.app.fragment + +import android.os.Bundle +import androidx.recyclerview.widget.RecyclerView.Adapter +import com.android.base.adapter.DataManager +import com.android.base.app.ui.AutoPageNumber +import com.android.base.app.ui.PageNumber +import com.android.base.app.ui.RefreshListLayout +import com.ztiany.loadmore.adapter.ILoadMore +import com.ztiany.loadmore.adapter.OnLoadMoreListener +import com.ztiany.loadmore.adapter.WrapperAdapter + +/** + * @author Ztiany + * date : 2016-03-19 23:09 + * email: 1169654504@qq.com + * @see [BaseListFragment] + */ +abstract class BaseListDialogFragment : BaseStateDialogFragment(), RefreshListLayout { + + /**加载更多*/ + private var loadMore: ILoadMore? = null + + /**列表数据管理*/ + private lateinit var dataManager: DataManager + + /**分页页码*/ + private var pageNumber: PageNumber? = null + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + if (!::dataManager.isInitialized) { + throw NullPointerException("you need set DataManager") + } + } + + protected fun setDataManager(dataManager: DataManager) { + this.dataManager = dataManager + } + + protected fun setupLoadMore(recyclerAdapter: Adapter<*>, pageNumber: PageNumber = AutoPageNumber(this, dataManager)): Adapter<*> { + this.pageNumber = pageNumber + + return WrapperAdapter.wrap(recyclerAdapter).apply { + setOnLoadMoreListener(object : OnLoadMoreListener { + override fun onLoadMore() { + this@BaseListDialogFragment.onLoadMore() + } + + override fun canLoadMore(): Boolean { + return !isRefreshing + } + }) + loadMore = this + } + } + + /**call by [.onRefresh] or [.onLoadMore], you can get current loading type from [.isRefreshing] or [.isLoadingMore].*/ + protected open fun onStartLoad() {} + + override fun onRefresh() = onStartLoad() + + protected fun onLoadMore() = onStartLoad() + + override fun canRefresh() = !isLoadingMore + + override fun replaceData(data: List) = dataManager.replaceAll(data) + + override fun addData(data: List) = dataManager.addItems(data) + + override fun isEmpty(): Boolean = dataManager.isEmpty + + override fun isLoadingMore(): Boolean = loadMore != null && loadMore?.isLoadingMore ?: false + + override fun getPager(): PageNumber = pageNumber + ?: throw NullPointerException("you need to call setupLoadMore to init pageNumber") + + fun loadMoreController(): ILoadMore = loadMore + ?: throw NullPointerException("you need to call setupLoadMore to init loadMoreController") + + override fun loadMoreCompleted(hasMore: Boolean) { + loadMore?.loadCompleted(hasMore) + } + + override fun loadMoreFailed() { + loadMore?.loadFail() + } + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/BaseListV2DialogFragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/BaseListV2DialogFragment.kt new file mode 100644 index 0000000..e711c4d --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/BaseListV2DialogFragment.kt @@ -0,0 +1,119 @@ +package com.android.base.app.fragment + +import android.os.Bundle +import android.view.View +import com.android.base.adapter.DataManager +import com.android.base.app.ui.AutoPageNumber +import com.android.base.app.ui.RefreshListLayout +import com.android.base.app.ui.StateLayoutConfig + +/** + * 区别于 [BaseListFragment] 只能支持 RecyclerView。[BaseListFragment] 采用包装 [androidx.recyclerview.widget.RecyclerView.Adapter] 的方式, + * 在底部添加 load more view 的 item,来实现加载更多。[BaseListV2DialogFragment] 没有采用此种方式,所以你使用的 RefreshView 应该是支持这下来刷新和加载更多功能的。 + * + * 在调用 [BaseListV2DialogFragment] 的 [onActivityCreated] 之前,你应该设置好 [dataManager]。 + * + *@author Ztiany + * Email: ztiany3@gmail.com + * Date : 2019-03-26 15:06 + */ +abstract class BaseListV2DialogFragment : BaseFragment(), RefreshListLayout { + + private lateinit var stateLayout: RefreshLoadMoreStateLayoutImpl + + protected open lateinit var dataManager: DataManager + + override fun internalOnViewPrepared(view: View, savedInstanceState: Bundle?) { + stateLayout = RefreshLoadMoreStateLayoutImpl.init(view) + stateLayout.refreshView.setRefreshHandler { + onRefresh() + } + stateLayout.refreshView.setLoadMoreHandler { + onLoadMore() + } + stateLayout.setStateRetryListener(this::onRetry) + } + + protected open fun onRetry(state: Int) { + if (!isRefreshing) { + autoRefresh() + } + } + + protected open fun onRefresh() = onStartLoad() + + protected open fun onLoadMore() = onStartLoad() + + /** call by [onRefresh] or [onLoadMore], you can get current loading type from [isRefreshing] or [isLoadingMore]. */ + protected open fun onStartLoad() {} + + override fun onActivityCreated(savedInstanceState: Bundle?) { + super.onActivityCreated(savedInstanceState) + if (!::dataManager.isInitialized) { + throw NullPointerException("you need set DataManager") + } + } + + override fun onDestroyView() { + super.onDestroyView() + refreshCompleted() + } + + override fun replaceData(data: MutableList?) { + dataManager.replaceAll(data) + } + + override fun addData(data: MutableList?) { + dataManager.addItems(data) + } + + fun setRefreshEnable(enable: Boolean) = stateLayout.refreshView.setRefreshEnable(enable) + + fun setLoadMoreEnable(enable: Boolean) = stateLayout.refreshView.setLoadMoreEnable(enable) + + override fun getPager() = AutoPageNumber(this, dataManager) + + override fun isEmpty() = dataManager.isEmpty + + override fun loadMoreCompleted(hasMore: Boolean) = stateLayout.refreshView.loadMoreCompleted(hasMore) + + override fun loadMoreFailed() = stateLayout.refreshView.loadMoreFailed() + + override fun isRefreshing() = stateLayout.refreshView.isRefreshing + + override fun showContentLayout() = stateLayout.showContentLayout() + + override fun showLoadingLayout() = stateLayout.showLoadingLayout() + + override fun refreshCompleted() = stateLayout.refreshView.refreshCompleted() + + override fun showEmptyLayout() = stateLayout.showEmptyLayout() + + override fun showErrorLayout() = stateLayout.showErrorLayout() + + override fun showRequesting() = stateLayout.showRequesting() + + override fun showBlank() = stateLayout.showBlank() + + override fun getStateLayoutConfig() = stateLayout.stateLayoutConfig + + override fun autoRefresh() = stateLayout.refreshView.autoRefresh() + + override fun showNetErrorLayout() = stateLayout.showNetErrorLayout() + + override fun showServerErrorLayout() = stateLayout.showServerErrorLayout() + + override fun isLoadingMore() = stateLayout.refreshView.isLoadingMore + + override fun currentStatus() = stateLayout.currentStatus() + + companion object { + const val CONTENT = StateLayoutConfig.CONTENT + const val LOADING = StateLayoutConfig.LOADING + const val ERROR = StateLayoutConfig.ERROR + const val EMPTY = StateLayoutConfig.EMPTY + const val NET_ERROR = StateLayoutConfig.NET_ERROR + const val SERVER_ERROR = StateLayoutConfig.SERVER_ERROR + } + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/BaseListV2Fragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/BaseListV2Fragment.kt index 24169a0..df3b57f 100644 --- a/lib_base/src/main/java/com/android/base/app/fragment/BaseListV2Fragment.kt +++ b/lib_base/src/main/java/com/android/base/app/fragment/BaseListV2Fragment.kt @@ -8,16 +8,12 @@ import com.android.base.app.ui.RefreshListLayout import com.android.base.app.ui.StateLayoutConfig /** - * 区别于 [BaseListFragment] 只能支持 RecyclerView。[BaseListFragment] 采用包装 [androidx.recyclerview.widget.RecyclerView.Adapter] 的方式, - * 在底部添加 load more view 的 item,来实现加载更多。BaseListV2Fragment 没有采用此种方式,所以你使用的刷新视图应该是支持这下来刷新和加载更多功能的。 - * - * 在调用BaseListV2Fragment [onActivityCreated] 之前,你应该设置好 [dataManager]。 - * *@author Ztiany * Email: ztiany3@gmail.com * Date : 2019-03-26 15:06 + *@see [BaseListV2Fragment] */ -abstract class BaseListV2Fragment : BaseFragment(), RefreshListLayout { +abstract class BaseListV2Fragment : BaseDialogFragment(), RefreshListLayout { private lateinit var stateLayout: RefreshLoadMoreStateLayoutImpl @@ -49,7 +45,7 @@ abstract class BaseListV2Fragment : BaseFragment(), RefreshListLayout { override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) - if (::dataManager.isInitialized) { + if (!::dataManager.isInitialized) { throw NullPointerException("you need set DataManager") } } @@ -72,22 +68,39 @@ abstract class BaseListV2Fragment : BaseFragment(), RefreshListLayout { fun setLoadMoreEnable(enable: Boolean) = stateLayout.refreshView.setLoadMoreEnable(enable) override fun getPager() = AutoPageNumber(this, dataManager) + override fun isEmpty() = dataManager.isEmpty + override fun loadMoreCompleted(hasMore: Boolean) = stateLayout.refreshView.loadMoreCompleted(hasMore) + override fun loadMoreFailed() = stateLayout.refreshView.loadMoreFailed() + override fun isRefreshing() = stateLayout.refreshView.isRefreshing + override fun showContentLayout() = stateLayout.showContentLayout() + override fun showLoadingLayout() = stateLayout.showLoadingLayout() + override fun refreshCompleted() = stateLayout.refreshView.refreshCompleted() + override fun showEmptyLayout() = stateLayout.showEmptyLayout() + override fun showErrorLayout() = stateLayout.showErrorLayout() + override fun showRequesting() = stateLayout.showRequesting() + override fun showBlank() = stateLayout.showBlank() + override fun getStateLayoutConfig() = stateLayout.stateLayoutConfig + override fun autoRefresh() = stateLayout.refreshView.autoRefresh() + override fun showNetErrorLayout() = stateLayout.showNetErrorLayout() + override fun showServerErrorLayout() = stateLayout.showServerErrorLayout() + override fun isLoadingMore() = stateLayout.refreshView.isLoadingMore + override fun currentStatus() = stateLayout.currentStatus() companion object { diff --git a/lib_base/src/main/java/com/android/base/app/fragment/BaseStateDialogFragment.java b/lib_base/src/main/java/com/android/base/app/fragment/BaseStateDialogFragment.java deleted file mode 100644 index b7cfe5e..0000000 --- a/lib_base/src/main/java/com/android/base/app/fragment/BaseStateDialogFragment.java +++ /dev/null @@ -1,151 +0,0 @@ -package com.android.base.app.fragment; - -import android.os.Bundle; -import android.view.View; - -import com.android.base.app.ui.RefreshStateLayout; -import com.android.base.app.ui.RefreshView; -import com.android.base.app.ui.StateLayoutConfig; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -/** - * @author Ztiany - * date : 2016-03-19 23:09 - * email: 1169654504@qq.com - * @see BaseStateFragment - */ -@SuppressWarnings("unused") -public abstract class BaseStateDialogFragment extends BaseDialogFragment implements RefreshStateLayout { - - private RefreshableStateLayoutImpl mStateLayout; - - protected static final int CONTENT = StateLayoutConfig.CONTENT; - protected static final int LOADING = StateLayoutConfig.LOADING; - protected static final int ERROR = StateLayoutConfig.ERROR; - protected static final int EMPTY = StateLayoutConfig.EMPTY; - protected static final int NET_ERROR = StateLayoutConfig.NET_ERROR; - protected static final int SERVER_ERROR = StateLayoutConfig.SERVER_ERROR; - - @Override - void internalOnViewPrepared(@NonNull View view, @Nullable Bundle savedInstanceState) { - mStateLayout = RefreshableStateLayoutImpl.init(view); - mStateLayout.setRefreshHandler(new RefreshView.RefreshHandler() { - @Override - public void onRefresh() { - BaseStateDialogFragment.this.onRefresh(); - } - - @Override - public boolean canRefresh() { - return BaseStateDialogFragment.this.canRefresh(); - } - }); - - mStateLayout.setStateRetryListenerUnchecked(this::onRetry); - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - refreshCompleted(); - } - - boolean canRefresh() { - return true; - } - - final RefreshView getRefreshView() { - return mStateLayout.getRefreshView(); - } - - protected void onRetry(@StateLayoutConfig.RetryableState int state) { - if (getRefreshView() != null) { - if (!getRefreshView().isRefreshing()) { - autoRefresh(); - } - } else { - onRefresh(); - } - } - - public final void setRefreshEnable(boolean enable) { - if (getRefreshView() != null) { - getRefreshView().setRefreshEnable(enable); - } - } - - protected void onRefresh() { - } - - @Override - public final StateLayoutConfig getStateLayoutConfig() { - return mStateLayout.getStateLayoutConfig(); - } - - private RefreshStateLayout getStateLayout() { - return mStateLayout; - } - - @Override - public final boolean isRefreshing() { - return mStateLayout.isRefreshing(); - } - - @Override - public void refreshCompleted() { - getStateLayout().refreshCompleted(); - } - - @Override - public void autoRefresh() { - getStateLayout().autoRefresh(); - } - - @Override - public void showContentLayout() { - getStateLayout().showContentLayout(); - } - - @Override - public void showLoadingLayout() { - getStateLayout().showLoadingLayout(); - } - - @Override - public void showEmptyLayout() { - getStateLayout().showEmptyLayout(); - } - - @Override - public void showErrorLayout() { - getStateLayout().showErrorLayout(); - } - - @Override - public void showRequesting() { - getStateLayout().showRequesting(); - } - - @Override - public void showBlank() { - getStateLayout().showBlank(); - } - - @Override - public void showNetErrorLayout() { - getStateLayout().showNetErrorLayout(); - } - - @Override - public void showServerErrorLayout() { - getStateLayout().showServerErrorLayout(); - } - - @Override - public int currentStatus() { - return mStateLayout.currentStatus(); - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/BaseStateDialogFragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/BaseStateDialogFragment.kt new file mode 100644 index 0000000..bdb42fa --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/BaseStateDialogFragment.kt @@ -0,0 +1,94 @@ +package com.android.base.app.fragment + +import android.os.Bundle +import android.view.View +import com.android.base.app.ui.RefreshStateLayout +import com.android.base.app.ui.RefreshView +import com.android.base.app.ui.StateLayoutConfig +import com.android.base.utils.common.ifNonNull +import com.android.base.utils.common.otherwise + +/** + * @author Ztiany + * date : 2016-03-19 23:09 + * email: 1169654504@qq.com + * @see BaseStateFragment + */ +abstract class BaseStateDialogFragment : BaseDialogFragment(), RefreshStateLayout { + + private lateinit var stateLayout: RefreshableStateLayoutImpl + + override fun internalOnViewPrepared(view: View, savedInstanceState: Bundle?) { + stateLayout = RefreshableStateLayoutImpl.init(view) + stateLayout.setRefreshHandler(object : RefreshView.RefreshHandler() { + override fun onRefresh() { + this@BaseStateDialogFragment.onRefresh() + } + + override fun canRefresh(): Boolean { + return this@BaseStateDialogFragment.canRefresh() + } + }) + stateLayout.setStateRetryListenerUnchecked { state -> onRetry(state) } + } + + override fun onDestroyView() { + super.onDestroyView() + refreshCompleted() + } + + internal open fun canRefresh() = true + + private val refreshView: RefreshView? + get() = stateLayout.refreshView + + protected open fun onRetry(@StateLayoutConfig.RetryableState state: Int) { + refreshView.ifNonNull { + if (this.isRefreshing) { + autoRefresh() + } + } otherwise { + onRefresh() + } + } + + protected open fun onRefresh() {} + + fun setRefreshEnable(enable: Boolean) = refreshView?.setRefreshEnable(enable) + + override fun getStateLayoutConfig(): StateLayoutConfig = stateLayout.stateLayoutConfig + + override fun isRefreshing() = stateLayout.isRefreshing + + override fun refreshCompleted() = stateLayout.refreshCompleted() + + override fun autoRefresh() = stateLayout.autoRefresh() + + override fun showContentLayout() = stateLayout.showContentLayout() + + override fun showLoadingLayout() = stateLayout.showLoadingLayout() + + override fun showEmptyLayout() = stateLayout.showEmptyLayout() + + override fun showErrorLayout() = stateLayout.showErrorLayout() + + override fun showRequesting() = stateLayout.showRequesting() + + override fun showBlank() = stateLayout.showBlank() + + override fun showNetErrorLayout() = stateLayout.showNetErrorLayout() + + override fun showServerErrorLayout() = stateLayout.showServerErrorLayout() + + override fun currentStatus() = stateLayout.currentStatus() + + companion object { + const val CONTENT = StateLayoutConfig.CONTENT + const val LOADING = StateLayoutConfig.LOADING + const val ERROR = StateLayoutConfig.ERROR + const val EMPTY = StateLayoutConfig.EMPTY + const val NET_ERROR = StateLayoutConfig.NET_ERROR + const val SERVER_ERROR = StateLayoutConfig.SERVER_ERROR + } + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/DefaultHorizontalAnimator.java b/lib_base/src/main/java/com/android/base/app/fragment/DefaultHorizontalAnimator.java deleted file mode 100644 index 4883b09..0000000 --- a/lib_base/src/main/java/com/android/base/app/fragment/DefaultHorizontalAnimator.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.android.base.app.fragment; - -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; - -import com.android.base.R; -import com.android.base.utils.BaseUtils; - - -public class DefaultHorizontalAnimator implements FragmentAnimator { - - @Override - public Animation makeOpenEnter() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_open_enter); - } - - @Override - public Animation makeOpenExit() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_open_exit); - } - - @Override - public Animation makeCloseEnter() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_close_enter); - } - - @Override - public Animation makeCloseExit() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_close_exit); - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/DefaultNoAnimator.java b/lib_base/src/main/java/com/android/base/app/fragment/DefaultNoAnimator.java deleted file mode 100644 index 4944d82..0000000 --- a/lib_base/src/main/java/com/android/base/app/fragment/DefaultNoAnimator.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.android.base.app.fragment; - - -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; - -import com.android.base.R; -import com.android.base.utils.BaseUtils; - -public class DefaultNoAnimator implements FragmentAnimator { - - @Override - public Animation makeOpenEnter() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim); - } - - @Override - public Animation makeOpenExit() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim); - } - - @Override - public Animation makeCloseEnter() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim); - } - - @Override - public Animation makeCloseExit() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim); - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/DefaultScaleAnimator.java b/lib_base/src/main/java/com/android/base/app/fragment/DefaultScaleAnimator.java deleted file mode 100644 index 5cd75ff..0000000 --- a/lib_base/src/main/java/com/android/base/app/fragment/DefaultScaleAnimator.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.android.base.app.fragment; - - -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.view.animation.AnimationSet; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; -import android.view.animation.ScaleAnimation; - - -public class DefaultScaleAnimator implements FragmentAnimator { - - private static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f); - private static final Interpolator DECELERATE_CUBIC = new DecelerateInterpolator(1.5f); - - private static final int ANIM_DUR = 220; - - @Override - public Animation makeOpenEnter() { - return makeOpenCloseAnimation(1.125f, 1.0f, 0, 1); - } - - @Override - public Animation makeOpenExit() { - return makeOpenCloseAnimation(1.0f, .975f, 1, 0); - } - - @Override - public Animation makeCloseEnter() { - return makeOpenCloseAnimation(.975f, 1.0f, 0, 1); - } - - @Override - public Animation makeCloseExit() { - return makeOpenCloseAnimation(1.0f, 1.075f, 1, 0); - } - - private static Animation makeOpenCloseAnimation(float startScale, float endScale, float startAlpha, float endAlpha) { - AnimationSet set = new AnimationSet(false); - - ScaleAnimation scale = new ScaleAnimation(startScale, endScale, startScale, endScale, - Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f); - scale.setInterpolator(DECELERATE_QUINT); - scale.setDuration(ANIM_DUR); - set.addAnimation(scale); - - AlphaAnimation alpha = new AlphaAnimation(startAlpha, endAlpha); - alpha.setInterpolator(DECELERATE_CUBIC); - alpha.setDuration(ANIM_DUR); - set.addAnimation(alpha); - - return set; - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/DefaultVerticalAnimator.java b/lib_base/src/main/java/com/android/base/app/fragment/DefaultVerticalAnimator.java deleted file mode 100644 index 418d4b6..0000000 --- a/lib_base/src/main/java/com/android/base/app/fragment/DefaultVerticalAnimator.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.android.base.app.fragment; - -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; - -import com.android.base.R; -import com.android.base.utils.BaseUtils; - -public class DefaultVerticalAnimator implements FragmentAnimator { - - @Override - public Animation makeOpenEnter() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_open_enter); - } - - @Override - public Animation makeOpenExit() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_open_exit); - } - - @Override - public Animation makeCloseEnter() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_close_enter); - } - - @Override - public Animation makeCloseExit() { - return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_close_exit); - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/DelegateEx.kt b/lib_base/src/main/java/com/android/base/app/fragment/DelegateEx.kt deleted file mode 100644 index 043e42d..0000000 --- a/lib_base/src/main/java/com/android/base/app/fragment/DelegateEx.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.android.base.app.fragment - -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KProperty - -/** - * 懒加载代理 - * - *@author Ztiany - * Email: ztiany3@gmail.com - * Date : 2019-03-08 12:50 - */ -class LazyLoad(private val onPrepared: (() -> Unit)) : ReadOnlyProperty { - - private lateinit var lazyDelegate: LazyDelegate - - override fun getValue(thisRef: BaseFragment, property: KProperty<*>): LazyDelegate { - if (!::lazyDelegate.isInitialized) { - lazyDelegate = LazyDelegate.attach(thisRef) { - onPrepared.invoke() - } - } - return lazyDelegate - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/FragmentAnimator.java b/lib_base/src/main/java/com/android/base/app/fragment/FragmentAnimator.java deleted file mode 100644 index 16b07e5..0000000 --- a/lib_base/src/main/java/com/android/base/app/fragment/FragmentAnimator.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.android.base.app.fragment; - -import android.view.animation.Animation; - -public interface FragmentAnimator { - - Animation makeOpenEnter(); - - Animation makeOpenExit(); - - Animation makeCloseEnter(); - - Animation makeCloseExit(); - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/FragmentDelegates.java b/lib_base/src/main/java/com/android/base/app/fragment/FragmentDelegates.java index d4155bf..5773325 100644 --- a/lib_base/src/main/java/com/android/base/app/fragment/FragmentDelegates.java +++ b/lib_base/src/main/java/com/android/base/app/fragment/FragmentDelegates.java @@ -5,6 +5,8 @@ import android.content.Intent; import android.os.Bundle; import android.view.View; +import com.android.base.app.fragment.delegates.FragmentDelegate; +import com.android.base.app.fragment.delegates.FragmentDelegateOwner; import com.github.dmstocking.optional.java.util.function.Predicate; import java.util.ArrayList; @@ -164,4 +166,4 @@ final class FragmentDelegates implements FragmentDelegate, FragmentDel return null; } -} +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/LazyDelegate.java b/lib_base/src/main/java/com/android/base/app/fragment/LazyDelegate.java deleted file mode 100644 index cb1a9ef..0000000 --- a/lib_base/src/main/java/com/android/base/app/fragment/LazyDelegate.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.android.base.app.fragment; - -import android.os.Bundle; -import android.view.View; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; - -/** - *
- *    在ViewPager中实现懒加载的Fragment
- *          changed--1: Android Support 24 把setUserVisibleHint方法放到了Attach之前调用了,所以请在在构造代码块中设置LazyDelegate
- * 
- * - * @author Ztiany - * Date : Date : 2016-05-06 15:02 - * Email: 1169654504@qq.com - */ -public class LazyDelegate implements FragmentDelegate { - - /** - * View是否准备好,如果不需要绑定view数据,只是加载网络数据,那么该字段可以去掉 - */ - private boolean mIsViewPrepared; - /** - * 滑动过来后,View是否可见 - */ - private boolean mIsViewVisible; - - private onPreparedListener mOnPreparedListener; - - private LazyDelegate() { - } - - public static LazyDelegate attach(FragmentDelegateOwner delegateFragment, final onPreparedListener onPreparedListener) { - LazyDelegate delegate = new LazyDelegate(); - delegate.mOnPreparedListener = onPreparedListener; - delegateFragment.addDelegate(delegate); - return delegate; - } - - /** - * 在这里实现Fragment数据的缓加载. - * - * @param isVisibleToUser true表用户可见,false表不可见 - */ - @Override - public void setUserVisibleHint(boolean isVisibleToUser) { - if (isVisibleToUser) { - mIsViewVisible = true; - onVisible(); - } else { - mIsViewVisible = false; - onInvisible(); - } - } - - @Override - public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { - mIsViewPrepared = true; - } - - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - lazyLoad(); - } - - /** - * 滑动过来后,界面可见时执行 - */ - @SuppressWarnings("all") - protected void onVisible() { - lazyLoad(); - } - - /** - * 滑动过来后,界面不可见时执行 - */ - @SuppressWarnings("all") - protected void onInvisible() { - } - - private void lazyLoad() { - if (mIsViewPrepared && mIsViewVisible) { - notifyLazyLoad(); - } - } - - /** - * 懒加载数据,并在此绑定View数据 - */ - private void notifyLazyLoad() { - if (mOnPreparedListener != null) { - mOnPreparedListener.onPrepared(); - } - } - - public interface onPreparedListener { - void onPrepared(); - } - - public static abstract class SimpleLazyLoadListener implements onPreparedListener { - - private boolean mIsCalled; - - @Override - public final void onPrepared() { - if (!mIsCalled) { - onFirstLoad(); - mIsCalled = true; - } - } - - protected abstract void onFirstLoad(); - } - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/LoadingViewFactory.java b/lib_base/src/main/java/com/android/base/app/fragment/LoadingViewFactory.java deleted file mode 100644 index 77295b4..0000000 --- a/lib_base/src/main/java/com/android/base/app/fragment/LoadingViewFactory.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.android.base.app.fragment; - -import android.content.Context; - -import com.android.base.app.ui.LoadingView; - -public interface LoadingViewFactory { - - LoadingView createLoadingDelegate(Context context); - -} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/animator/FragmentAnimator.kt b/lib_base/src/main/java/com/android/base/app/fragment/animator/FragmentAnimator.kt new file mode 100644 index 0000000..f4fa4b8 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/animator/FragmentAnimator.kt @@ -0,0 +1,103 @@ +package com.android.base.app.fragment.animator + +import android.view.animation.* +import com.android.base.R +import com.android.base.utils.BaseUtils + +interface FragmentAnimator { + fun makeOpenEnter(): Animation? + fun makeOpenExit(): Animation? + fun makeCloseEnter(): Animation? + fun makeCloseExit(): Animation? +} + +class DefaultVerticalAnimator : FragmentAnimator { + override fun makeOpenEnter(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_open_enter) + } + + override fun makeOpenExit(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_open_exit) + } + + override fun makeCloseEnter(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_close_enter) + } + + override fun makeCloseExit(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.v_fragment_close_exit) + } +} + +class DefaultHorizontalAnimator : FragmentAnimator { + override fun makeOpenEnter(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_open_enter) + } + + override fun makeOpenExit(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_open_exit) + } + + override fun makeCloseEnter(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_close_enter) + } + + override fun makeCloseExit(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.h_fragment_close_exit) + } +} + +class DefaultNoAnimator : FragmentAnimator { + override fun makeOpenEnter(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim) + } + + override fun makeOpenExit(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim) + } + + override fun makeCloseEnter(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim) + } + + override fun makeCloseExit(): Animation? { + return AnimationUtils.loadAnimation(BaseUtils.getAppContext(), R.anim.base_no_anim) + } +} + + +class DefaultScaleAnimator : FragmentAnimator { + override fun makeOpenEnter(): Animation? { + return makeOpenCloseAnimation(1.125f, 1.0f, 0f, 1f) + } + + override fun makeOpenExit(): Animation? { + return makeOpenCloseAnimation(1.0f, .975f, 1f, 0f) + } + + override fun makeCloseEnter(): Animation? { + return makeOpenCloseAnimation(.975f, 1.0f, 0f, 1f) + } + + override fun makeCloseExit(): Animation? { + return makeOpenCloseAnimation(1.0f, 1.075f, 1f, 0f) + } + + companion object { + private val DECELERATE_QUINT: Interpolator = DecelerateInterpolator(2.5f) + private val DECELERATE_CUBIC: Interpolator = DecelerateInterpolator(1.5f) + private const val ANIM_DUR = 220 + private fun makeOpenCloseAnimation(startScale: Float, endScale: Float, startAlpha: Float, endAlpha: Float): Animation { + val set = AnimationSet(false) + val scale = ScaleAnimation(startScale, endScale, startScale, endScale, Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f) + scale.interpolator = DECELERATE_QUINT + scale.duration = ANIM_DUR.toLong() + set.addAnimation(scale) + val alpha = AlphaAnimation(startAlpha, endAlpha) + alpha.interpolator = DECELERATE_CUBIC + alpha.duration = ANIM_DUR.toLong() + set.addAnimation(alpha) + return set + } + } +} diff --git a/lib_base/src/main/java/com/android/base/app/fragment/FragmentAnimatorHelper.java b/lib_base/src/main/java/com/android/base/app/fragment/animator/FragmentAnimatorHelper.java similarity index 90% rename from lib_base/src/main/java/com/android/base/app/fragment/FragmentAnimatorHelper.java rename to lib_base/src/main/java/com/android/base/app/fragment/animator/FragmentAnimatorHelper.java index 0c8c44e..0e9c762 100644 --- a/lib_base/src/main/java/com/android/base/app/fragment/FragmentAnimatorHelper.java +++ b/lib_base/src/main/java/com/android/base/app/fragment/animator/FragmentAnimatorHelper.java @@ -1,4 +1,4 @@ -package com.android.base.app.fragment; +package com.android.base.app.fragment.animator; import android.content.Context; import android.view.animation.Animation; @@ -7,15 +7,17 @@ import android.view.animation.AnimationUtils; import com.android.base.R; import androidx.fragment.app.FragmentTransaction; +import timber.log.Timber; public final class FragmentAnimatorHelper { private Context context; private FragmentAnimator fragmentAnimator; - FragmentAnimatorHelper(Context context, FragmentAnimator fragmentAnimator) { + public FragmentAnimatorHelper(Context context, FragmentAnimator fragmentAnimator) { this.context = context; this.fragmentAnimator = fragmentAnimator; + Timber.d("context %s, animator %s", context.toString(), fragmentAnimator.toString()); } public void changeAnimation(FragmentAnimator fragmentAnimator) { @@ -83,7 +85,7 @@ public final class FragmentAnimatorHelper { } } - Animation onCreateAnimation(int transit, boolean enter) { + public Animation onCreateAnimation(int transit, boolean enter) { if (transit == FragmentTransaction.TRANSIT_FRAGMENT_OPEN) { if (enter) { return initEnterAnim(); diff --git a/lib_base/src/main/java/com/android/base/app/fragment/FragmentDelegate.java b/lib_base/src/main/java/com/android/base/app/fragment/delegates/FragmentDelegate.java similarity index 96% rename from lib_base/src/main/java/com/android/base/app/fragment/FragmentDelegate.java rename to lib_base/src/main/java/com/android/base/app/fragment/delegates/FragmentDelegate.java index 9a1c2b0..4ceb617 100644 --- a/lib_base/src/main/java/com/android/base/app/fragment/FragmentDelegate.java +++ b/lib_base/src/main/java/com/android/base/app/fragment/delegates/FragmentDelegate.java @@ -1,4 +1,4 @@ -package com.android.base.app.fragment; +package com.android.base.app.fragment.delegates; import android.content.Context; import android.content.Intent; diff --git a/lib_base/src/main/java/com/android/base/app/fragment/FragmentDelegateOwner.java b/lib_base/src/main/java/com/android/base/app/fragment/delegates/FragmentDelegateOwner.java similarity index 88% rename from lib_base/src/main/java/com/android/base/app/fragment/FragmentDelegateOwner.java rename to lib_base/src/main/java/com/android/base/app/fragment/delegates/FragmentDelegateOwner.java index 0532150..f7ca7ca 100644 --- a/lib_base/src/main/java/com/android/base/app/fragment/FragmentDelegateOwner.java +++ b/lib_base/src/main/java/com/android/base/app/fragment/delegates/FragmentDelegateOwner.java @@ -1,4 +1,4 @@ -package com.android.base.app.fragment; +package com.android.base.app.fragment.delegates; import com.github.dmstocking.optional.java.util.function.Predicate; diff --git a/lib_base/src/main/java/com/android/base/app/fragment/delegates/LazyDelegate.kt b/lib_base/src/main/java/com/android/base/app/fragment/delegates/LazyDelegate.kt new file mode 100644 index 0000000..34ad803 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/delegates/LazyDelegate.kt @@ -0,0 +1,124 @@ +package com.android.base.app.fragment.delegates + +import android.os.Bundle +import android.view.View +import androidx.fragment.app.Fragment +import com.android.base.app.fragment.BaseFragment +import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty + +/** + * 用于在ViewPager中实现懒加载的Fragment: + * + * - changed-1: Android Support 24 把 setUserVisibleHint 方法放到了Attach 之前调用了,所以请在在构造代码块中设置 LazyDelegate。 + * + * @author Ztiany + * Date : Date : 2016-05-06 15:02 + * Email: 1169654504@qq.com + */ +open class LazyDelegate private constructor() : FragmentDelegate { + + /** View是否准备好,如果不需要绑定view数据,只是加载网络数据,那么该字段可以去掉 */ + private var mIsViewPrepared = false + + /** 滑动过来后,View是否可见 */ + private var mIsViewVisible = false + + private var mOnPreparedListener: (() -> Unit)? = null + + /** + * 在这里实现Fragment数据的缓加载. + * + * @param isVisibleToUser true 表用户可见,false 表不可见 + */ + override fun setUserVisibleHint(isVisibleToUser: Boolean) { + if (isVisibleToUser) { + mIsViewVisible = true + onVisible() + } else { + mIsViewVisible = false + onInvisible() + } + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle) { + mIsViewPrepared = true + } + + override fun onActivityCreated(savedInstanceState: Bundle?) { + lazyLoad() + } + + /** + * 滑动过来后,界面可见时执行 + */ + protected fun onVisible() { + lazyLoad() + } + + /** + * 滑动过来后,界面不可见时执行 + */ + protected fun onInvisible() {} + + private fun lazyLoad() { + if (mIsViewPrepared && mIsViewVisible) { + notifyLazyLoad() + } + } + + /** + * 懒加载数据,并在此绑定View数据 + */ + private fun notifyLazyLoad() { + mOnPreparedListener?.invoke() + } + + companion object { + fun attach(delegateFragment: FragmentDelegateOwner, onPreparedListener: () -> Unit): LazyDelegate { + val delegate = LazyDelegate() + delegate.mOnPreparedListener = onPreparedListener + delegateFragment.addDelegate(delegate) + return delegate + } + } + +} + +class SimpleLazyLoadListener(private val onFirstLoad: () -> Unit) : (() -> Unit) { + + private var mIsCalled = false + + override fun invoke() { + if (!mIsCalled) { + onFirstLoad() + mIsCalled = true + } + } + +} + + +/** + * 懒加载代理 + * + *@author Ztiany + * Email: ztiany3@gmail.com + * Date : 2019-03-08 12:50 + */ +class LazyLoad(private val once: Boolean = true, private val onPrepared: (() -> Unit)) : ReadOnlyProperty { + + private lateinit var lazyDelegate: LazyDelegate + + override fun getValue(thisRef: BaseFragment, property: KProperty<*>): LazyDelegate { + if (!::lazyDelegate.isInitialized) { + lazyDelegate = if (once) { + LazyDelegate.attach(thisRef, SimpleLazyLoadListener(onPrepared)) + } else { + LazyDelegate.attach(thisRef, onPrepared) + } + } + return lazyDelegate + } + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectableEx.kt b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectableEx.kt new file mode 100644 index 0000000..f60cfe3 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectableEx.kt @@ -0,0 +1,29 @@ +package com.android.base.app.fragment.injectable + +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.android.base.data.ErrorHandler + + +interface InjectableEx { + + val viewModelFactory: ViewModelProvider.Factory + + val errorHandler: ErrorHandler + +} + +inline fun InjectableEx.injectViewModel(fragment: Fragment): Lazy { + return fragment.viewModels { viewModelFactory } +} + +inline fun InjectableEx.injectActivityViewModel(fragment: Fragment): Lazy { + return fragment.viewModels( + ownerProducer = { + fragment.requireActivity() + } + ) { viewModelFactory } +} + diff --git a/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseDialogFragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseDialogFragment.kt new file mode 100644 index 0000000..3464e59 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseDialogFragment.kt @@ -0,0 +1,20 @@ +package com.android.base.app.fragment.injectable + +import androidx.lifecycle.ViewModelProvider +import com.android.base.app.dagger.Injectable +import com.android.base.app.fragment.BaseDialogFragment +import com.android.base.data.ErrorHandler +import javax.inject.Inject + +/** + *@author Ztiany + * Email: ztiany3@gmail.com + * Date : 2019-01-15 12:57 + */ +open class InjectorBaseDialogFragment : BaseDialogFragment(), Injectable, InjectableEx { + + @Inject override lateinit var viewModelFactory: ViewModelProvider.Factory + + @Inject override lateinit var errorHandler: ErrorHandler + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseFragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseFragment.kt new file mode 100644 index 0000000..363d947 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseFragment.kt @@ -0,0 +1,20 @@ +package com.android.base.app.fragment.injectable + +import androidx.lifecycle.ViewModelProvider +import com.android.base.app.dagger.Injectable +import com.android.base.app.fragment.BaseFragment +import com.android.base.data.ErrorHandler +import javax.inject.Inject + +/** + *@author Ztiany + * Email: ztiany3@gmail.com + * Date : 2019-01-15 12:57 + */ +open class InjectorBaseFragment : BaseFragment(), Injectable, InjectableEx { + + @Inject override lateinit var viewModelFactory: ViewModelProvider.Factory + + @Inject override lateinit var errorHandler: ErrorHandler + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseListFragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseListFragment.kt new file mode 100644 index 0000000..36cd71a --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseListFragment.kt @@ -0,0 +1,20 @@ +package com.android.base.app.fragment.injectable + +import androidx.lifecycle.ViewModelProvider +import com.android.base.app.dagger.Injectable +import com.android.base.app.fragment.BaseListFragment +import com.android.base.data.ErrorHandler +import javax.inject.Inject + +/** + *@author Ztiany + * Email: ztiany3@gmail.com + * Date : 2019-01-15 12:57 + */ +open class InjectorBaseListFragment : BaseListFragment(), Injectable, InjectableEx { + + @Inject override lateinit var viewModelFactory: ViewModelProvider.Factory + + @Inject override lateinit var errorHandler: ErrorHandler + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseListV2Fragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseListV2Fragment.kt new file mode 100644 index 0000000..8602a32 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseListV2Fragment.kt @@ -0,0 +1,20 @@ +package com.android.base.app.fragment.injectable + +import androidx.lifecycle.ViewModelProvider +import com.android.base.app.dagger.Injectable +import com.android.base.app.fragment.BaseListV2Fragment +import com.android.base.data.ErrorHandler +import javax.inject.Inject + +/** + *@author Ztiany + * Email: ztiany3@gmail.com + * Date : 2019-01-15 12:57 + */ +open class InjectorBaseListV2Fragment : BaseListV2Fragment(), Injectable, InjectableEx { + + @Inject override lateinit var viewModelFactory: ViewModelProvider.Factory + + @Inject override lateinit var errorHandler: ErrorHandler + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseStateDialogFragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseStateDialogFragment.kt new file mode 100644 index 0000000..e629601 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseStateDialogFragment.kt @@ -0,0 +1,20 @@ +package com.android.base.app.fragment.injectable + +import androidx.lifecycle.ViewModelProvider +import com.android.base.app.dagger.Injectable +import com.android.base.app.fragment.BaseStateDialogFragment +import com.android.base.data.ErrorHandler +import javax.inject.Inject + +/** + *@author Ztiany + * Email: ztiany3@gmail.com + * Date : 2019-01-15 12:57 + */ +open class InjectorBaseStateDialogFragment : BaseStateDialogFragment(), Injectable, InjectableEx { + + @Inject override lateinit var viewModelFactory: ViewModelProvider.Factory + + @Inject override lateinit var errorHandler: ErrorHandler + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseStateFragment.kt b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseStateFragment.kt new file mode 100644 index 0000000..898945b --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/fragment/injectable/InjectorBaseStateFragment.kt @@ -0,0 +1,20 @@ +package com.android.base.app.fragment.injectable + +import androidx.lifecycle.ViewModelProvider +import com.android.base.app.dagger.Injectable +import com.android.base.app.fragment.BaseStateFragment +import com.android.base.data.ErrorHandler +import javax.inject.Inject + +/** + *@author Ztiany + * Email: ztiany3@gmail.com + * Date : 2019-01-15 12:57 + */ +open class InjectorBaseStateFragment : BaseStateFragment(), Injectable, InjectableEx { + + @Inject override lateinit var viewModelFactory: ViewModelProvider.Factory + + @Inject override lateinit var errorHandler: ErrorHandler + +} \ No newline at end of file diff --git a/lib_base/src/main/java/com/android/base/app/fragment/FragmentConfig.java b/lib_base/src/main/java/com/android/base/app/fragment/tools/FragmentConfig.java similarity index 82% rename from lib_base/src/main/java/com/android/base/app/fragment/FragmentConfig.java rename to lib_base/src/main/java/com/android/base/app/fragment/tools/FragmentConfig.java index 6aa7f96..57701b5 100644 --- a/lib_base/src/main/java/com/android/base/app/fragment/FragmentConfig.java +++ b/lib_base/src/main/java/com/android/base/app/fragment/tools/FragmentConfig.java @@ -1,4 +1,6 @@ -package com.android.base.app.fragment; +package com.android.base.app.fragment.tools; + +import com.android.base.app.fragment.animator.FragmentAnimator; /** * @author Ztiany @@ -26,7 +28,7 @@ public class FragmentConfig { sFragmentAnimator = animator; } - static FragmentAnimator defaultFragmentAnimator() { + public static FragmentAnimator defaultFragmentAnimator() { return sFragmentAnimator; } diff --git a/lib_base/src/main/java/com/android/base/app/fragment/FragmentInfo.java b/lib_base/src/main/java/com/android/base/app/fragment/tools/FragmentInfo.java similarity index 98% rename from lib_base/src/main/java/com/android/base/app/fragment/FragmentInfo.java rename to lib_base/src/main/java/com/android/base/app/fragment/tools/FragmentInfo.java index 002cfa2..080cf79 100644 --- a/lib_base/src/main/java/com/android/base/app/fragment/FragmentInfo.java +++ b/lib_base/src/main/java/com/android/base/app/fragment/tools/FragmentInfo.java @@ -1,4 +1,4 @@ -package com.android.base.app.fragment; +package com.android.base.app.fragment.tools; import android.content.Context; import android.os.Bundle; diff --git a/lib_base/src/main/java/com/android/base/app/fragment/Fragments.kt b/lib_base/src/main/java/com/android/base/app/fragment/tools/Fragments.kt similarity index 97% rename from lib_base/src/main/java/com/android/base/app/fragment/Fragments.kt rename to lib_base/src/main/java/com/android/base/app/fragment/tools/Fragments.kt index 97bd1c2..d185006 100644 --- a/lib_base/src/main/java/com/android/base/app/fragment/Fragments.kt +++ b/lib_base/src/main/java/com/android/base/app/fragment/tools/Fragments.kt @@ -1,6 +1,6 @@ @file:JvmName("Fragments") -package com.android.base.app.fragment +package com.android.base.app.fragment.tools import android.view.View @@ -11,7 +11,9 @@ import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentTransaction import com.android.base.app.activity.ActivityDelegate import com.android.base.app.activity.ActivityDelegateOwner -import com.android.base.app.activity.ActivityStatus +import com.android.base.app.activity.ActivityState +import com.android.base.app.fragment.delegates.FragmentDelegate +import com.android.base.app.fragment.delegates.FragmentDelegateOwner import com.android.base.utils.common.javaClassName import kotlin.reflect.KClass @@ -219,7 +221,7 @@ private class SafelyFragmentTransactionActivityDelegate : ActivityDelegate { diff --git a/lib_base/src/main/java/com/android/base/app/ui/LoadingView.java b/lib_base/src/main/java/com/android/base/app/ui/LoadingView.java deleted file mode 100644 index f7b0895..0000000 --- a/lib_base/src/main/java/com/android/base/app/ui/LoadingView.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.android.base.app.ui; - - -import androidx.annotation.StringRes; - -/** - * 显示通用的 LoadingDialog 和 Message - * - * @author Ztiany - * Email: 1169654504@qq.com - * Date : 2016-12-02 15:12 - */ -public interface LoadingView { - - void showLoadingDialog(); - - void showLoadingDialog(boolean cancelable); - - void showLoadingDialog(CharSequence message, boolean cancelable); - - void showLoadingDialog(@StringRes int messageId, boolean cancelable); - - void dismissLoadingDialog(); - - void showMessage(CharSequence message); - - void showMessage(@StringRes int messageId); - -} diff --git a/lib_base/src/main/java/com/android/base/app/ui/LoadingView.kt b/lib_base/src/main/java/com/android/base/app/ui/LoadingView.kt new file mode 100644 index 0000000..8aed40b --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/ui/LoadingView.kt @@ -0,0 +1,22 @@ +package com.android.base.app.ui + +import androidx.annotation.StringRes + +/** + * 显示通用的 LoadingDialog 和 Message + * + * @author Ztiany + * Email: 1169654504@qq.com + * Date : 2016-12-02 15:12 + */ +interface LoadingView { + + fun showLoadingDialog() + fun showLoadingDialog(cancelable: Boolean) + fun showLoadingDialog(message: CharSequence, cancelable: Boolean) + fun showLoadingDialog(@StringRes messageId: Int, cancelable: Boolean) + fun dismissLoadingDialog() + fun showMessage(message: CharSequence) + fun showMessage(@StringRes messageId: Int) + +} \ No newline at end of file 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 new file mode 100644 index 0000000..a72fcb3 --- /dev/null +++ b/lib_base/src/main/java/com/android/base/app/ui/LoadingViewFactory.kt @@ -0,0 +1,9 @@ +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/RefreshViewFactory.java b/lib_base/src/main/java/com/android/base/app/ui/RefreshViewFactory.java index de9b499..ab42c2b 100644 --- a/lib_base/src/main/java/com/android/base/app/ui/RefreshViewFactory.java +++ b/lib_base/src/main/java/com/android/base/app/ui/RefreshViewFactory.java @@ -16,7 +16,6 @@ public class RefreshViewFactory { private static Factory sFactory; public static RefreshView createRefreshView(View view) { - if (sFactory != null) { return sFactory.createRefreshView(view); } diff --git a/lib_base/src/main/java/com/android/base/app/ui/SwipeRefreshView.java b/lib_base/src/main/java/com/android/base/app/ui/SwipeRefreshView.java index a8af188..511448f 100644 --- a/lib_base/src/main/java/com/android/base/app/ui/SwipeRefreshView.java +++ b/lib_base/src/main/java/com/android/base/app/ui/SwipeRefreshView.java @@ -49,4 +49,5 @@ class SwipeRefreshView implements RefreshView { public void setRefreshEnable(boolean enable) { mSwipeRefreshLayout.setEnabled(enable); } + } diff --git a/lib_base/src/main/java/com/android/base/data/ErrorHandler.kt b/lib_base/src/main/java/com/android/base/data/ErrorHandler.kt new file mode 100644 index 0000000..76af4ee --- /dev/null +++ b/lib_base/src/main/java/com/android/base/data/ErrorHandler.kt @@ -0,0 +1,25 @@ +package com.android.base.data + + +/** + * 异常处理器 + * + * @author Ztiany + * Email: ztiany3@gmail.com + * Date : 2018-11-08 16:02 + */ +interface ErrorHandler { + + /** 根据异常,生成一个合理的错误提示 */ + fun createMessage(throwable: Throwable): CharSequence + + /** 直接处理异常,比如根据 [createMessage] 方法生成的消息弹出一个 toast。 */ + fun handleError(throwable: Throwable) + + /** 直接处理异常,自定义消息处理*/ + fun handleError(throwable: Throwable, processor: ((CharSequence) -> Unit)) + + /**处理全局异常,此方法仅由数据层调用,用于统一处理全局异常*/ + fun handleGlobalError(throwable: Throwable) + +}