parent
							
								
									ab079cf9a5
								
							
						
					
					
						commit
						069cd7db7f
					
				| @ -1,310 +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 android.view.ViewParent; | ||||
| import android.view.animation.Animation; | ||||
| 
 | ||||
| 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.fragment.app.Fragment; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
| /** | ||||
|  * 提供: | ||||
|  * <pre> | ||||
|  *     1. RxJava 生命周期绑定。 | ||||
|  *     2. 返回键监听。 | ||||
|  *     3. 显示 LoadingDialog 和 Message。 | ||||
|  *     4. 可以添加生命周期代理。 | ||||
|  * </pre> | ||||
|  * | ||||
|  * @author Ztiany | ||||
|  * date :   2016-03-19 23:09 | ||||
|  * email:    1169654504@qq.com | ||||
|  */ | ||||
| public class BaseFragment extends Fragment implements LoadingView, OnBackPressListener, FragmentDelegateOwner { | ||||
| 
 | ||||
|     private LoadingView mLoadingViewImpl; | ||||
| 
 | ||||
|     private View mLayoutView; | ||||
| 
 | ||||
|     /* just for cache*/ | ||||
|     private View mCachedView; | ||||
| 
 | ||||
|     private FragmentAnimatorHelper mFragmentAnimatorHelper; | ||||
| 
 | ||||
|     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"); | ||||
|         } | ||||
| 
 | ||||
|         Timber.tag(tag()).d("mCachedView.parent: " + mCachedView.getParent()); | ||||
| 
 | ||||
|         if (mCachedView.getParent() != null) { | ||||
|             ViewParent parent = mCachedView.getParent(); | ||||
|             if (parent instanceof ViewGroup) { | ||||
|                 ((ViewGroup) parent).removeView(mCachedView); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         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<FragmentDelegate> 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 = onCreateLoadingView(); | ||||
|         } | ||||
|         if (mLoadingViewImpl == null) { | ||||
|             mLoadingViewImpl = Sword.get().getLoadingViewFactory().createLoadingDelegate(getContext()); | ||||
|         } | ||||
|         return mLoadingViewImpl; | ||||
|     } | ||||
| 
 | ||||
|     protected LoadingView onCreateLoadingView() { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     @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); | ||||
|     } | ||||
| 
 | ||||
|     @Nullable | ||||
|     @Override | ||||
|     public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) { | ||||
|         if (mFragmentAnimatorHelper == null) { | ||||
|             mFragmentAnimatorHelper = new FragmentAnimatorHelper(getContext(), FragmentConfig.defaultFragmentAnimator()); | ||||
|         } | ||||
|         return mFragmentAnimatorHelper.onCreateAnimation(transit, enter); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,263 @@ | ||||
| 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 android.view.animation.Animation | ||||
| import androidx.annotation.StringRes | ||||
| import androidx.annotation.UiThread | ||||
| 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.ui.LoadingView | ||||
| import com.github.dmstocking.optional.java.util.function.Predicate | ||||
| import timber.log.Timber | ||||
| 
 | ||||
| /** | ||||
|  *基础 BaseFragment 封装: | ||||
|  * | ||||
|  * 1. RxJava 生命周期绑定。 | ||||
|  * 2. 返回键监听。 | ||||
|  * 3. 显示 LoadingDialog 和 Message。 | ||||
|  * 4. 可以添加生命周期代理。 | ||||
|  * | ||||
|  * @author Ztiany | ||||
|  * date :   2016-03-19 23:09 | ||||
|  * email:    1169654504@qq.com | ||||
|  */ | ||||
| open class BaseFragment : Fragment(), LoadingView, OnBackPressListener, FragmentDelegateOwner { | ||||
| 
 | ||||
|     private var loadingView: LoadingView? = null | ||||
| 
 | ||||
|     private var layoutView: View? = null | ||||
| 
 | ||||
|     /** just for cache*/ | ||||
|     private var cachedView: View? = null | ||||
| 
 | ||||
|     private var fragmentAnimatorHelper: FragmentAnimatorHelper? = 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<String>, 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<*>?>?): 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(context) | ||||
|         } | ||||
|         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) | ||||
|     } | ||||
| 
 | ||||
|     override fun onCreateAnimation(transit: Int, enter: Boolean, nextAnim: Int): Animation? { | ||||
|         if (fragmentAnimatorHelper == null) { | ||||
|             fragmentAnimatorHelper = FragmentAnimatorHelper(context, FragmentConfig.defaultFragmentAnimator()) | ||||
|         } | ||||
|         return fragmentAnimatorHelper!!.onCreateAnimation(transit, enter) | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -1,151 +0,0 @@ | ||||
| package com.android.base.app.fragment; | ||||
| 
 | ||||
| import android.os.Bundle; | ||||
| 
 | ||||
| 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; | ||||
| 
 | ||||
| import java.util.List; | ||||
| 
 | ||||
| import androidx.annotation.NonNull; | ||||
| import androidx.annotation.Nullable; | ||||
| import androidx.recyclerview.widget.RecyclerView; | ||||
| 
 | ||||
| /** | ||||
|  * 通用的RecyclerView列表界面:支持下拉刷新和加载更多。 | ||||
|  * | ||||
|  * @param <T> 当前列表使用的数据类型 | ||||
|  * @author Ztiany | ||||
|  * date :   2016-03-19 23:09 | ||||
|  * email:    1169654504@qq.com | ||||
|  */ | ||||
| public abstract class BaseListFragment<T> extends BaseStateFragment implements RefreshListLayout<T> { | ||||
| 
 | ||||
|     /** | ||||
|      * 加载更多 | ||||
|      */ | ||||
|     private ILoadMore mLoadMore; | ||||
| 
 | ||||
|     /** | ||||
|      * 列表数据管理 | ||||
|      */ | ||||
|     private DataManager<T> mDataManager; | ||||
| 
 | ||||
|     /** | ||||
|      * 分页页码 | ||||
|      */ | ||||
|     private PageNumber mPageNumber; | ||||
| 
 | ||||
|     @Override | ||||
|     public void onActivityCreated(@Nullable Bundle savedInstanceState) { | ||||
|         super.onActivityCreated(savedInstanceState); | ||||
|         if (mDataManager == null) { | ||||
|             throw new NullPointerException("you need set DataManager"); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected final void setDataManager(@NonNull DataManager<T> dataManager) { | ||||
|         mDataManager = dataManager; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Default PageNumber is {@link AutoPageNumber} | ||||
|      * | ||||
|      * @param recyclerAdapter adapter | ||||
|      * @return recycler adapter wrapper | ||||
|      */ | ||||
|     protected final RecyclerView.Adapter setupLoadMore(@NonNull RecyclerView.Adapter<?> recyclerAdapter) { | ||||
|         if (mDataManager == null) { | ||||
|             throw new IllegalStateException("you should setup a DataManager before call this method"); | ||||
|         } | ||||
|         return setupLoadMore(recyclerAdapter, new AutoPageNumber(this, mDataManager)); | ||||
|     } | ||||
| 
 | ||||
|     protected final RecyclerView.Adapter setupLoadMore(@NonNull RecyclerView.Adapter<?> recyclerAdapter, @NonNull PageNumber pageNumber) { | ||||
|         mPageNumber = pageNumber; | ||||
| 
 | ||||
|         WrapperAdapter wrap = WrapperAdapter.wrap(recyclerAdapter); | ||||
|         mLoadMore = wrap; | ||||
|         mLoadMore.setOnLoadMoreListener(new OnLoadMoreListener() { | ||||
|             @Override | ||||
|             public void onLoadMore() { | ||||
|                 BaseListFragment.this.onLoadMore(); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public boolean canLoadMore() { | ||||
|                 return !isRefreshing(); | ||||
|             } | ||||
|         }); | ||||
|         return wrap; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void onRefresh() { | ||||
|         onStartLoad(); | ||||
|     } | ||||
| 
 | ||||
|     protected void onLoadMore() { | ||||
|         onStartLoad(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     final boolean canRefresh() { | ||||
|         return !isLoadingMore(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * call by {@link #onRefresh()} or {@link #onLoadMore()}, you can get current loading type from {@link #isRefreshing()} or {@link #isLoadingMore()}. | ||||
|      */ | ||||
|     protected void onStartLoad() { | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void replaceData(List<T> data) { | ||||
|         mDataManager.replaceAll(data); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void addData(List<T> data) { | ||||
|         mDataManager.addItems(data); | ||||
|     } | ||||
| 
 | ||||
|     protected final ILoadMore getLoadMoreController() { | ||||
|         return mLoadMore; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public PageNumber getPager() { | ||||
|         return mPageNumber; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean isEmpty() { | ||||
|         return mDataManager.isEmpty(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public boolean isLoadingMore() { | ||||
|         return mLoadMore != null && mLoadMore.isLoadingMore(); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void loadMoreCompleted(boolean hasMore) { | ||||
|         if (mLoadMore != null) { | ||||
|             mLoadMore.loadCompleted(hasMore); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     public void loadMoreFailed() { | ||||
|         if (mLoadMore != null) { | ||||
|             mLoadMore.loadFail(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -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 | ||||
| 
 | ||||
| /** | ||||
|  * 通用的基于 RecyclerView 的列表界面,支持下拉刷新和加载更多。 | ||||
|  * | ||||
|  * @param <T> 当前列表使用的数据类型 | ||||
|  * @author Ztiany | ||||
|  * date :   2016-03-19 23:09 | ||||
|  * email:    1169654504@qq.com | ||||
|  */ | ||||
| abstract class BaseListFragment<T> : BaseStateFragment(), RefreshListLayout<T> { | ||||
| 
 | ||||
|     /**加载更多*/ | ||||
|     private var loadMore: ILoadMore? = null | ||||
| 
 | ||||
|     /**列表数据管理*/ | ||||
|     private lateinit var dataManager: DataManager<T> | ||||
| 
 | ||||
|     /**分页页码*/ | ||||
|     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<T>) { | ||||
|         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@BaseListFragment.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<T>)=  dataManager.replaceAll(data) | ||||
| 
 | ||||
|     override fun addData(data: List<T>) =   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() | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -1,158 +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; | ||||
| 
 | ||||
| /** | ||||
|  * <pre> | ||||
|  *          1: 支持显示{CONTENT、LOADING、ERROR、EMPTY}四种布局、支持下拉刷新 | ||||
|  *          2: 使用的布局中必须有一个id = R.id.base_status_layout的Layout,切改Layout实现了StateLayout | ||||
|  *          3: RefreshView(下拉刷新)的id必须设置为 :R.id.refresh_layout,没有添加则表示不需要下拉刷新功能 | ||||
|  *          4: 默认所有重试和下拉刷新都会调用{@link #onRefresh()},子类可以修改该行为 | ||||
|  * </pre> | ||||
|  * | ||||
|  * @author Ztiany | ||||
|  * date :   2016-03-19 23:09 | ||||
|  * email:    1169654504@qq.com | ||||
|  */ | ||||
| @SuppressWarnings("unused") | ||||
| public abstract class BaseStateFragment extends BaseFragment 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() { | ||||
|                 BaseStateFragment.this.onRefresh(); | ||||
|             } | ||||
| 
 | ||||
|             @Override | ||||
|             public boolean canRefresh() { | ||||
|                 return BaseStateFragment.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(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     protected void onRefresh() { | ||||
|     } | ||||
| 
 | ||||
|     public final void setRefreshEnable(boolean enable) { | ||||
|         if (getRefreshView() != null) { | ||||
|             getRefreshView().setRefreshEnable(enable); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     @NonNull | ||||
|     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(); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,101 @@ | ||||
| package com.android.base.app.fragment | ||||
| 
 | ||||
| import android.os.Bundle | ||||
| import android.view.View | ||||
| import com.android.base.R | ||||
| import com.android.base.app.ui.RefreshStateLayout | ||||
| import com.android.base.app.ui.RefreshView | ||||
| import com.android.base.app.ui.RefreshView.RefreshHandler | ||||
| import com.android.base.app.ui.StateLayoutConfig | ||||
| import com.android.base.app.ui.StateLayoutConfig.RetryableState | ||||
| import com.android.base.utils.common.ifNonNull | ||||
| import com.android.base.utils.common.otherwise | ||||
| 
 | ||||
| /** | ||||
|  * 1. 支持显示{CONTENT, LOADING, ERROR, EMPTY}等状态布局、支持下拉刷新 | ||||
|  * 2. 使用的布局中必须有一个id = [R.id.base_state_layout] 的 Layout,确保 Layout 实现了[com.android.base.app.ui.StateLayout] | ||||
|  * 3. [RefreshView] (下拉刷新)的 id 必须设置为 :[R.id.base_refresh_layout],没有添加则表示不需要下拉刷新功能 | ||||
|  * 4. 默认所有重试和下拉刷新都会调用 [onRefresh],子类可以修改该行为 | ||||
|  * | ||||
|  * @author Ztiany | ||||
|  * date :   2016-03-19 23:09 | ||||
|  * email:    1169654504@qq.com | ||||
|  */ | ||||
| abstract class BaseStateFragment : BaseFragment(), RefreshStateLayout { | ||||
| 
 | ||||
|     private lateinit var stateLayout: RefreshableStateLayoutImpl | ||||
| 
 | ||||
|     override fun internalOnViewPrepared(view: View, savedInstanceState: Bundle?) { | ||||
|         stateLayout = RefreshableStateLayoutImpl.init(view) | ||||
|         stateLayout.setRefreshHandler(object : RefreshHandler() { | ||||
|             override fun onRefresh() { | ||||
|                 this@BaseStateFragment.onRefresh() | ||||
|             } | ||||
| 
 | ||||
|             override fun canRefresh(): Boolean { | ||||
|                 return this@BaseStateFragment.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(@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 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue