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