parent
069cd7db7f
commit
24de572943
@ -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<Any> |
||||
|
||||
override fun androidInjector() = androidInjector |
||||
|
||||
} |
@ -1,6 +1,6 @@ |
||||
package com.android.base.app.activity |
||||
|
||||
enum class ActivityStatus { |
||||
enum class ActivityState { |
||||
INITIALIZED, |
||||
CREATE, |
||||
START, |
@ -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; |
||||
|
||||
/** |
||||
* <pre> |
||||
* 1,封装通用流程。 |
||||
* 2,onBackPressed 事件分发,优先交给 Fragment 处理。 |
||||
* 3,提供 RxJava 的生命周期绑定。 |
||||
* </pre> |
||||
* |
||||
* @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<ActivityDelegate> 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; |
||||
} |
||||
} |
||||
|
||||
} |
@ -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<String>, 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<*>?>?): 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 |
||||
} |
||||
} |
||||
|
||||
} |
@ -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<Object> androidInjector; |
||||
|
||||
@Override |
||||
public AndroidInjector<Object> androidInjector() { |
||||
return androidInjector; |
||||
} |
||||
|
||||
} |
@ -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; |
||||
|
||||
/** |
||||
* 提供: |
||||
* <pre> |
||||
* 1. RxJava 生命周期绑定。 |
||||
* 2. 返回键监听。 |
||||
* 3. 显示 LoadingDialog 和 Message。 |
||||
* 4. 可以添加生命周期代理。 |
||||
* </pre> |
||||
* |
||||
* @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<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 = 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); |
||||
} |
||||
|
||||
} |
@ -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<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(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) |
||||
} |
||||
|
||||
} |
@ -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<T> : BaseStateDialogFragment(), 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@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<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() |
||||
} |
||||
|
||||
} |
@ -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<T> : BaseFragment(), RefreshListLayout<T> { |
||||
|
||||
private lateinit var stateLayout: RefreshLoadMoreStateLayoutImpl |
||||
|
||||
protected open lateinit var dataManager: DataManager<T> |
||||
|
||||
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<T>?) { |
||||
dataManager.replaceAll(data) |
||||
} |
||||
|
||||
override fun addData(data: MutableList<T>?) { |
||||
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 |
||||
} |
||||
|
||||
} |
@ -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(); |
||||
} |
||||
|
||||
} |
@ -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 |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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; |
||||
} |
||||
|
||||
} |
@ -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); |
||||
} |
||||
|
||||
} |
@ -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<BaseFragment, LazyDelegate> { |
||||
|
||||
private lateinit var lazyDelegate: LazyDelegate |
||||
|
||||
override fun getValue(thisRef: BaseFragment, property: KProperty<*>): LazyDelegate { |
||||
if (!::lazyDelegate.isInitialized) { |
||||
lazyDelegate = LazyDelegate.attach(thisRef) { |
||||
onPrepared.invoke() |
||||
} |
||||
} |
||||
return lazyDelegate |
||||
} |
||||
|
||||
} |
@ -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(); |
||||
|
||||
} |
@ -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; |
||||
|
||||
/** |
||||
* <pre> |
||||
* 在ViewPager中实现懒加载的Fragment |
||||
* changed--1: Android Support 24 把setUserVisibleHint方法放到了Attach之前调用了,所以请在在构造代码块中设置LazyDelegate |
||||
* </pre> |
||||
* |
||||
* @author Ztiany |
||||
* Date : Date : 2016-05-06 15:02 |
||||
* Email: 1169654504@qq.com |
||||
*/ |
||||
public class LazyDelegate implements FragmentDelegate<Fragment> { |
||||
|
||||
/** |
||||
* 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(); |
||||
} |
||||
|
||||
} |
@ -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); |
||||
|
||||
} |
@ -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 |
||||
} |
||||
} |
||||
} |
@ -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; |
@ -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; |
@ -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<Fragment?> { |
||||
|
||||
/** 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<BaseFragment, LazyDelegate> { |
||||
|
||||
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 |
||||
} |
||||
|
||||
} |
@ -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 <reified VM : ViewModel> InjectableEx.injectViewModel(fragment: Fragment): Lazy<VM> { |
||||
return fragment.viewModels { viewModelFactory } |
||||
} |
||||
|
||||
inline fun <reified VM : ViewModel> InjectableEx.injectActivityViewModel(fragment: Fragment): Lazy<VM> { |
||||
return fragment.viewModels( |
||||
ownerProducer = { |
||||
fragment.requireActivity() |
||||
} |
||||
) { viewModelFactory } |
||||
} |
||||
|
@ -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 |
||||
|
||||
} |
@ -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 |
||||
|
||||
} |
@ -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<T> : BaseListFragment<T>(), Injectable, InjectableEx { |
||||
|
||||
@Inject override lateinit var viewModelFactory: ViewModelProvider.Factory |
||||
|
||||
@Inject override lateinit var errorHandler: ErrorHandler |
||||
|
||||
} |
@ -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<T> : BaseListV2Fragment<T>(), Injectable, InjectableEx { |
||||
|
||||
@Inject override lateinit var viewModelFactory: ViewModelProvider.Factory |
||||
|
||||
@Inject override lateinit var errorHandler: ErrorHandler |
||||
|
||||
} |
@ -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 |
||||
|
||||
} |
@ -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 |
||||
|
||||
} |
@ -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; |
@ -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); |
||||
|
||||
} |
@ -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) |
||||
|
||||
} |
@ -0,0 +1,9 @@ |
||||
package com.android.base.app.ui |
||||
|
||||
import android.content.Context |
||||
|
||||
interface LoadingViewFactory { |
||||
|
||||
fun createLoadingDelegate(context: Context): LoadingView |
||||
|
||||
} |
@ -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) |
||||
|
||||
} |
Loading…
Reference in new issue