version:1.0.0

update:更换包名
bugfixes:
This commit is contained in:
2024-07-11 10:30:46 +08:00
parent ed06e2903c
commit a8c6e48435
412 changed files with 1654 additions and 1722 deletions

View File

@@ -0,0 +1,159 @@
package com.xxpatx.os.base;
import android.app.Application;
import android.content.Intent;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;
import com.alibaba.sdk.android.push.CloudPushService;
import com.alibaba.sdk.android.push.CommonCallback;
import com.alibaba.sdk.android.push.noonesdk.PushServiceFactory;
import com.arialyy.aria.core.Aria;
import com.hjq.toast.Toaster;
import com.qweather.sdk.view.HeConfig;
import com.tencent.bugly.crashreport.CrashReport;
import com.tencent.mmkv.MMKV;
import com.xxpatx.os.BuildConfig;
import com.xxpatx.os.alarm.AlarmUtils;
import com.xxpatx.os.db.WechatContactManager;
import com.xxpatx.os.manager.AmapManager;
import com.xxpatx.os.manager.AppManager;
import com.xxpatx.os.manager.AppStatusManager;
import com.xxpatx.os.manager.ConnectManager;
import com.xxpatx.os.manager.RemoteManager;
import com.xxpatx.os.network.NetInterfaceManager;
import com.xxpatx.os.push.PushManager;
import com.xxpatx.os.service.main.MainService;
import com.xxpatx.os.shortcut.ShortcutUtils;
import com.xxpatx.os.utils.AppUsedTimeUtils;
import com.xxpatx.os.utils.JGYUtils;
import com.xxpatx.os.utils.WiFiUtils;
public class BaseApplication extends Application {
private static final String TAG = BaseApplication.class.getSimpleName();
@Override
public void onCreate() {
super.onCreate();
if (!BuildConfig.DEBUG) {
catchException();
}
String rootDir = MMKV.initialize(this);
Log.e(TAG, "mmkv root: " + rootDir);
// 初始化 Toast 框架
Toaster.init(this);
CrashReport.initCrashReport(getApplicationContext(), "f65d7a4361", false);
CrashReport.setDeviceModel(getApplicationContext(), Build.MODEL);
xcrash.XCrash.init(this);
aliyunPushInit();
PushManager.init(this);
Aria.init(this);
Aria.get(this).getDownloadConfig().setMaxTaskNum(1);
Aria.get(this).getDownloadConfig().setConvertSpeed(true);
AppManager.init(this);
WiFiUtils.init(this);
AppUsedTimeUtils.init(this);
AlarmUtils.init(this);
ShortcutUtils.init(this);
AmapManager.init(this);
HeConfig.init("HE2210211540591362", "fe42a7bb59b14eefb27eea4fb2c40e99");
//切换至开发版服务
HeConfig.switchToDevService();
RemoteManager.init(this);
ConnectManager.init(this);
AppStatusManager.init(this);
NetInterfaceManager.init(this);
JGYUtils.init(this);
try {
startService(new Intent(this, MainService.class));
} catch (Exception e) {
Log.e(TAG, "onCreate: " + e.getMessage());
}
WechatContactManager.init(this);
}
private void aliyunPushInit() {
PushServiceFactory.init(this);
final CloudPushService pushService = PushServiceFactory.getCloudPushService();
pushService.setLogLevel(CloudPushService.LOG_DEBUG);
pushService.register(this, new CommonCallback() {
@Override
public void onSuccess(String response) {
Log.e("AliyunPush", "init cloudchannel success");
Log.e("AliyunPush", "init cloudchannel success " + pushService.getDeviceId());
String sn = RemoteManager.getInstance().getSerial();
if (TextUtils.isEmpty(sn)) {
return;
}
pushService.bindAccount(sn, new CommonCallback() {
@Override
public void onSuccess(String s) {
Log.e("AliyunPush", "bind account " + sn + " success\n");
}
@Override
public void onFailed(String errorCode, String errorMsg) {
Log.e("AliyunPush", "bind account " + sn + " failed." +
"errorCode: " + errorCode + ", errorMsg:" + errorMsg);
}
});
pushService.addAlias(sn, new CommonCallback() {
@Override
public void onSuccess(String s) {
Log.e("AliyunPush", "add alias " + sn + " success\n");
}
@Override
public void onFailed(String errorCode, String errorMsg) {
Log.e("AliyunPush", "add alias " + sn + " failed." +
"errorCode: " + errorCode + ", errorMsg:" + errorMsg + "\n");
}
});
}
@Override
public void onFailed(String errorCode, String errorMessage) {
Log.e("AliyunPush", "init cloudchannel failed -- errorcode:" + errorCode + " -- errorMessage:" + errorMessage);
}
});
}
private void catchException() {
Thread.setDefaultUncaughtExceptionHandler(
new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
Log.e("捕获异常子线程:", Thread.currentThread().getName() +
"在:" + e.getStackTrace()[0].getClassName());
}
}
);
//下面是新增方法!
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
while (true) {
try {
Looper.loop(); //会先执行这个方法,然后在执行下面的异常捕获方法!
} catch (Exception e) {
Log.e("捕获异常主线程:", Thread.currentThread().getName() + "在:" + e.getStackTrace()[0].getClassName());
e.printStackTrace();
}
}
}
});
}
}

View File

@@ -0,0 +1,68 @@
package com.xxpatx.os.base;
import android.os.Bundle;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import com.xxpatx.os.R;
import com.xxpatx.os.base.rx.BaseRxActivity;
import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
public abstract class BaseDataBindingActivity extends BaseRxActivity {
public BaseDataBindingActivity() {
super();
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// StatusBarUtil.init(this);
UltimateBarX.statusBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
.light(setNightMode())
.fitWindow(setfitWindow())
.apply();
UltimateBarX.navigationBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
.light(setNightMode())
.fitWindow(setfitWindow())
.apply();
initDataBinding();
initView();
initData();
}
/**
* @return 是否是黑色状态栏
*/
// protected abstract boolean setNightMode();
public boolean setNightMode() {
return false;
}
/**
* @return 是否是入侵
*/
// protected abstract boolean setNightMode();
public boolean setfitWindow() {
return false;
}
protected abstract void initDataBinding();
/**
* 初始化视图
*/
protected abstract void initView();
/**
* 初始化数据
*/
protected abstract void initData();
}

View File

@@ -0,0 +1,44 @@
package com.xxpatx.os.base;
import android.os.Bundle;
import com.xxpatx.os.base.rx.BaseRxFragment;
public abstract class BaseFragment extends BaseRxFragment {
protected boolean isViewInitiated;
protected boolean isVisibleToUser;
protected boolean isDataInitiated;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
isViewInitiated = true;
prepareFetchData();
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
this.isVisibleToUser = isVisibleToUser;
prepareFetchData();
}
public abstract void fetchData();
public boolean prepareFetchData() {
return prepareFetchData(false);
}
public boolean prepareFetchData(boolean forceUpdate) {
if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
fetchData();
//注释掉保证每次都更新数据
// isDataInitiated = true;
return true;
}
return false;
}
}

View File

@@ -0,0 +1,205 @@
package com.xxpatx.os.base;
import android.util.SparseArray;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.fragment.app.FragmentTransaction;
import java.util.List;
/**
* 加载显示Fragment的ViewPagerAdapter基类
* 提供可以刷新的方法
*
* @author Fly
* @e-mail 1285760616@qq.com
* @time 2018/3/22
*/
public class BaseFragmentPagerAdapter extends FragmentPagerAdapter {
private List<Fragment> mFragmentList;
private FragmentManager mFragmentManager;
/**下面两个值用来保存Fragment的位置信息用以判断该位置是否需要更新*/
private SparseArray<String> mFragmentPositionMap;
private SparseArray<String> mFragmentPositionMapAfterUpdate;
public BaseFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
mFragmentList = fragments;
mFragmentManager = fm;
mFragmentList = fragments;
mFragmentPositionMap = new SparseArray<>();
mFragmentPositionMapAfterUpdate = new SparseArray<>();
setFragmentPositionMap();
setFragmentPositionMapForUpdate();
}
/**
* 保存更新之前的位置信息,用<hashCode, position>的键值对结构来保存
*/
private void setFragmentPositionMap() {
mFragmentPositionMap.clear();
for (int i = 0; i < mFragmentList.size(); i++) {
mFragmentPositionMap.put(Long.valueOf(getItemId(i)).intValue(), String.valueOf(i));
}
}
/**
* 保存更新之后的位置信息,用<hashCode, position>的键值对结构来保存
*/
private void setFragmentPositionMapForUpdate() {
mFragmentPositionMapAfterUpdate.clear();
for (int i = 0; i < mFragmentList.size(); i++) {
mFragmentPositionMapAfterUpdate.put(Long.valueOf(getItemId(i)).intValue(), String.valueOf(i));
}
}
/**
* 在此方法中找到需要更新的位置返回POSITION_NONE否则返回POSITION_UNCHANGED即可
*/
@Override
public int getItemPosition(Object object) {
int hashCode = object.hashCode();
//查找object在更新后的列表中的位置
String position = mFragmentPositionMapAfterUpdate.get(hashCode);
//更新后的列表中不存在该object的位置了
if (position == null) {
return POSITION_NONE;
} else {
//如果更新后的列表中存在该object的位置, 查找该object之前的位置并判断位置是否发生了变化
int size = mFragmentPositionMap.size();
for (int i = 0; i < size ; i++) {
int key = mFragmentPositionMap.keyAt(i);
if (key == hashCode) {
String index = mFragmentPositionMap.get(key);
if (position.equals(index)) {
//位置没变依然返回POSITION_UNCHANGED
return POSITION_UNCHANGED;
} else {
//位置变了
return POSITION_NONE;
}
}
}
}
return POSITION_UNCHANGED;
}
/**
* 将指定的Fragment替换/更新为新的Fragment
* @param oldFragment 旧Fragment
* @param newFragment 新Fragment
*/
public void replaceFragment(Fragment oldFragment, Fragment newFragment) {
int position = mFragmentList.indexOf(oldFragment);
if (position == -1) {
return;
}
//从Transaction移除旧的Fragment
removeFragmentInternal(oldFragment);
//替换List中对应的Fragment
mFragmentList.set(position, newFragment);
//刷新Adapter
notifyItemChanged();
}
/**
* 将指定位置的Fragment替换/更新为新的Fragment同{@link #replaceFragment(Fragment oldFragment, Fragment newFragment)}
* @param position 旧Fragment的位置
* @param newFragment 新Fragment
*/
public void replaceFragment(int position, Fragment newFragment) {
Fragment oldFragment = mFragmentList.get(position);
removeFragmentInternal(oldFragment);
mFragmentList.set(position, newFragment);
notifyItemChanged();
notifyDataSetChanged();
}
/**
* 移除指定的Fragment
* @param fragment 目标Fragment
*/
public void removeFragment(Fragment fragment) {
//先从List中移除
mFragmentList.remove(fragment);
//然后从Transaction移除
removeFragmentInternal(fragment);
//最后刷新Adapter
notifyItemChanged();
}
/**
* 移除指定位置的Fragment同 {@link #removeFragment(Fragment fragment)}
* @param position
*/
public void removeFragment(int position) {
Fragment fragment = mFragmentList.get(position);
//然后从List中移除
mFragmentList.remove(fragment);
//先从Transaction移除
removeFragmentInternal(fragment);
//最后刷新Adapter
notifyItemChanged();
}
/**
* 添加Fragment
* @param fragment 目标Fragment
*/
public void addFragment(Fragment fragment) {
mFragmentList.add(fragment);
notifyItemChanged();
}
/**
* 在指定位置插入一个Fragment
* @param position 插入位置
* @param fragment 目标Fragment
*/
public void insertFragment(int position, Fragment fragment) {
mFragmentList.add(position, fragment);
notifyItemChanged();
}
public void notifyItemChanged() {
//刷新之前重新收集位置信息
setFragmentPositionMapForUpdate();
notifyDataSetChanged();
setFragmentPositionMap();
}
/**
* 从Transaction移除Fragment
* @param fragment 目标Fragment
*/
private void removeFragmentInternal(Fragment fragment) {
FragmentTransaction transaction = mFragmentManager.beginTransaction();
transaction.remove(fragment);
transaction.commitAllowingStateLoss();
}
/**
* 此方法不用position做返回值即可破解fragment tag异常的错误
*/
@Override
public long getItemId(int position) {
// 获取当前数据的hashCode其实这里不用hashCode用自定义的可以关联当前Item对象的唯一值也可以只要不是直接返回position
return mFragmentList.get(position).hashCode();
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public List<Fragment> getFragments() {
return mFragmentList;
}
}

View File

@@ -0,0 +1,100 @@
package com.xxpatx.os.base;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
/**
* Author: wangjie
* Email: tiantian.china.2@gmail.com
* Date: 1/23/15.
*/
public abstract class BaseLazyFragment extends Fragment {
private static final String TAG = BaseLazyFragment.class.getSimpleName();
private boolean isPrepared;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initPrepare();
}
/**
* 第一次onResume中的调用onUserVisible避免操作与onFirstUserVisible操作重复
*/
private boolean isFirstResume = true;
@Override
public void onResume() {
super.onResume();
if (isFirstResume) {
isFirstResume = false;
return;
}
if (getUserVisibleHint()) {
onUserVisible();
}
}
@Override
public void onPause() {
super.onPause();
if (getUserVisibleHint()) {
onUserInvisible();
}
}
private boolean isFirstVisible = true;
private boolean isFirstInvisible = true;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
if (isFirstVisible) {
isFirstVisible = false;
initPrepare();
} else {
onUserVisible();
}
} else {
if (isFirstInvisible) {
isFirstInvisible = false;
onFirstUserInvisible();
} else {
onUserInvisible();
}
}
}
public synchronized void initPrepare() {
if (isPrepared) {
onFirstUserVisible();
} else {
isPrepared = true;
}
}
/**
* 第一次fragment可见进行初始化工作
*/
public abstract void onFirstUserVisible();
/**
* fragment可见切换回来或者onResume
*/
public abstract void onUserVisible();
/**
* 第一次fragment不可见不建议在此处理事件
*/
public abstract void onFirstUserInvisible();
/**
* fragment不可见切换掉或者onPause
*/
public abstract void onUserInvisible();
}

View File

@@ -0,0 +1,87 @@
package com.xxpatx.os.base;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import com.hjq.toast.Toaster;
import com.tencent.mmkv.MMKV;
import com.xxpatx.os.R;
import com.xxpatx.os.base.rx.BaseRxActivity;
import com.xxpatx.os.config.CommonConfig;
import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
public abstract class BaseTransparentActivity extends BaseRxActivity {
private static final String TAG = BaseTransparentActivity.class.getSimpleName();
private MMKV mmkv = MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE);
public BaseTransparentActivity() {
super();
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// StatusBarUtil.init(this);
UltimateBarX.statusBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
.light(setNightMode())
.fitWindow(setfitWindow())
.apply();
UltimateBarX.navigationBar(this)
.transparent()
.colorRes(R.color.colorPrimaryDark)
.light(setNightMode())
.fitWindow(setfitWindow())
.apply();
}
/**
* 设置布局
*/
protected abstract int getLayoutId();
/**
* @return 是否是黑色状态栏
*/
// protected abstract boolean setNightMode();
public boolean setNightMode() {
return false;
}
/**
* @return 是否是入侵
*/
// protected abstract boolean setNightMode();
public boolean setfitWindow() {
return false;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP://增大系统媒体音量
case KeyEvent.KEYCODE_VOLUME_DOWN://减小系统媒体音量
return getVolumeKeyStatus();
default:
break;
}
return super.onKeyDown(keyCode, event);
}
public boolean getVolumeKeyStatus() {
boolean disableKey = mmkv.decodeBool(CommonConfig.DISABLE_VOLUME_KEY, false);
Log.e(TAG, "getVolumeKeyStatus: disableKey = " + disableKey);
if (disableKey){
Toaster.showLong("音量键已被禁用");
}
return disableKey;
}
}

View File

@@ -0,0 +1,118 @@
package com.xxpatx.os.base;
import android.content.Context;
import android.widget.ImageView;
import androidx.annotation.NonNull;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.luck.picture.lib.engine.ImageEngine;
import com.luck.picture.lib.utils.ActivityCompatHelper;
import com.xxpatx.os.R;
/**
* @authorluck
* @date2019-11-13 17:02
* @describeGlide加载引擎
*/
public class GlideEngine implements ImageEngine {
/**
* 加载图片
*
* @param context 上下文
* @param url 资源url
* @param imageView 图片承载控件
*/
@Override
public void loadImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.load(url)
.into(imageView);
}
@Override
public void loadImage(Context context, ImageView imageView, String url, int maxWidth, int maxHeight) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.load(url)
.override(maxWidth, maxHeight)
.into(imageView);
}
/**
* 加载相册目录封面
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadAlbumCover(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.asBitmap()
.load(url)
.override(180, 180)
.sizeMultiplier(0.5f)
.transform(new CenterCrop(), new RoundedCorners(8))
.placeholder(R.drawable.ps_image_placeholder)
.into(imageView);
}
/**
* 加载图片列表图片
*
* @param context 上下文
* @param url 图片路径
* @param imageView 承载图片ImageView
*/
@Override
public void loadGridImage(@NonNull Context context, @NonNull String url, @NonNull ImageView imageView) {
if (!ActivityCompatHelper.assertValidRequest(context)) {
return;
}
Glide.with(context)
.load(url)
.override(200, 200)
.centerCrop()
.placeholder(R.drawable.ps_image_placeholder)
.into(imageView);
}
@Override
public void pauseRequests(Context context) {
Glide.with(context).pauseRequests();
}
@Override
public void resumeRequests(Context context) {
Glide.with(context).resumeRequests();
}
private GlideEngine() {
}
private static GlideEngine instance;
public static GlideEngine createGlideEngine() {
if (null == instance) {
synchronized (GlideEngine.class) {
if (null == instance) {
instance = new GlideEngine();
}
}
}
return instance;
}
}

View File

@@ -0,0 +1,35 @@
package com.xxpatx.os.base.mvp;
import android.os.Bundle;
import androidx.annotation.CallSuper;
import androidx.annotation.Nullable;
import com.xxpatx.os.base.BaseTransparentActivity;
@Deprecated
public abstract class BaseMvpActivity extends BaseTransparentActivity {
public BaseMvpActivity() {
super();
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(getLayoutId());
initView();
initData();
}
/**
* 初始化视图
*/
protected abstract void initView();
/**
* 初始化数据
*/
protected abstract void initData();
}

View File

@@ -0,0 +1,8 @@
package com.xxpatx.os.base.mvp;
@Deprecated
public interface BasePresenter<V extends BaseView> {
void attachView(V view);
void detachView();
}

View File

@@ -0,0 +1,6 @@
package com.xxpatx.os.base.mvp;
@Deprecated
public interface BaseView {
}

View File

@@ -0,0 +1,54 @@
package com.xxpatx.os.base.mvvm;
import android.os.Bundle;
import android.util.Log;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import com.xxpatx.os.base.BaseTransparentActivity;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
public abstract class BaseMvvmActivity<VM extends ViewModel, VDB extends ViewDataBinding> extends BaseTransparentActivity {
private static final String TAG = BaseMvvmActivity.class.getSimpleName();
protected VM mViewModel;
protected VDB mViewDataBinding;
protected Class<VM> vmClass;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//ViewDataBinding
mViewDataBinding = DataBindingUtil.setContentView(this, getLayoutId());
mViewDataBinding.setLifecycleOwner(this);
//ViewModel
vmClass = (Class<VM>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
boolean isAbstract = Modifier.isAbstract(vmClass.getModifiers());
Log.e(TAG, "isLocalClass:" + vmClass.getSimpleName().equals(ViewModel.class.getSimpleName()) + " isAbstract:" + isAbstract);
if (!isAbstract) {//不是一个抽象类
mViewModel = new ViewModelProvider(this).get(vmClass);
}
initDataBinding();
initView();
initData();
}
protected abstract void initDataBinding();
/**
* 初始化视图
*/
protected abstract void initView();
/**
* 初始化数据
*/
protected abstract void initData();
}

View File

@@ -0,0 +1,71 @@
package com.xxpatx.os.base.mvvm;
import android.content.Context;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.ViewModel;
import java.lang.ref.WeakReference;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
/**
* 所有viewmodel的基类
*/
public abstract class BaseViewModel<VDB extends ViewDataBinding, T> extends ViewModel implements ViewDataBindingCallback {
/**
* 当前viewmodel对应的页面binding
*/
protected VDB binding;
@Override
public void setVDBinding(ViewDataBinding vdBinding) {
binding = (VDB) vdBinding;
}
@Override
public VDB getVDBinding() {
if (binding == null) {
throw new NullPointerException("BaseViewModel >> getVDBinding >> null!!!");
}
return binding;
}
/**
* 上下文
*/
private WeakReference<Context> ctx;
@Override
public void setCtx(Context context) {
if (ctx == null) {
ctx = new WeakReference<>(context);
}
}
@Override
public Context getCtx() {
if (ctx == null) {
throw new NullPointerException("BaseViewModel >> getCtx >> null!!!");
}
return ctx.get();
}
public abstract void onDestroy();
private BehaviorSubject<T> mBehaviorSubject;
@Override
public void setLifecycle(BehaviorSubject subject) {
this.mBehaviorSubject = (BehaviorSubject<T>) subject;
}
@Override
public BehaviorSubject<T> getLifecycle() {
return mBehaviorSubject;
}
}

View File

@@ -0,0 +1,26 @@
package com.xxpatx.os.base.mvvm;
import android.content.Context;
import androidx.databinding.ViewDataBinding;
import com.trello.rxlifecycle4.android.ActivityEvent;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
public interface ViewDataBindingCallback<VDB extends ViewDataBinding> {
void setVDBinding(VDB binding);
VDB getVDBinding() throws NullPointerException;
void setCtx(Context context);
Context getCtx() throws NullPointerException;
void setLifecycle(BehaviorSubject<ActivityEvent> subject);
BehaviorSubject<ActivityEvent> getLifecycle();
}

View File

@@ -0,0 +1,311 @@
package com.xxpatx.os.base.mvvm.fragment;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import androidx.annotation.CallSuper;
import androidx.annotation.CheckResult;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import com.trello.rxlifecycle4.LifecycleProvider;
import com.trello.rxlifecycle4.LifecycleTransformer;
import com.trello.rxlifecycle4.RxLifecycle;
import com.trello.rxlifecycle4.android.FragmentEvent;
import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
import java.lang.ref.WeakReference;
import java.lang.reflect.ParameterizedType;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
public abstract class BaseMvvmDialogFragment<VM extends ViewModel, VDB extends ViewDataBinding> extends DialogFragment implements LifecycleProvider<FragmentEvent> {
/**
* 是否顯示了
*/
protected boolean mIsVisible;
/**
* 是否準備好了-Created
*/
protected boolean mHasPrepare;
protected VM mViewModel;
protected VDB mViewDataBinding;
protected Class<VM> vmClass;
//
protected Toolbar toolbar;
protected View statusBarView;
//
protected Bundle bundle;//来自getArguments()
protected Bundle savedInstanceState;
/**
* 上下文
*/
private WeakReference<Context> ctx;
public Context getCtx() {
return ctx == null ? null : ctx.get();
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
ctx = new WeakReference<>(context);
}
/**
* onCreate、onResume里不能调用
*
* @return
*/
public boolean isAttached() {
boolean flag = getCtx() != null && isAdded();
Log.d("BaseMvvmDialogFragment", " >> isAttached >> flag: " + flag);
return flag;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
//ViewDataBinding
mViewDataBinding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
mViewDataBinding.setLifecycleOwner(this);
//ViewModel
vmClass = (Class<VM>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
mViewModel = new ViewModelProvider(this).get(vmClass);
//
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
return mViewDataBinding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
lifecycleSubject.onNext(FragmentEvent.CREATE_VIEW);
if (initStatusBarToolBar()) {
toolbar = getToolbar();
}
// //注册eventbus
// if (getClass().isAnnotationPresent(BindEventBus.class))
// EventBusManager.register(this);
// //
fitsLayoutOverlap();
initView(bundle = getArguments());
//
initData(this.savedInstanceState = savedInstanceState);
//
if (mIsVisible) {
onEnter();
}
mHasPrepare = true;
}
@Override
public void onDestroyView() {
lifecycleSubject.onNext(FragmentEvent.DESTROY_VIEW);
super.onDestroyView();
mHasPrepare = false;
mViewDataBinding = null;
// //移除eventbus
// if (getClass().isAnnotationPresent(BindEventBus.class))
// EventBusManager.unregister(this);
// //
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (mIsVisible == getUserVisibleHint())
return;
mIsVisible = getUserVisibleHint();
if (mIsVisible) {
if (!mHasPrepare)
return;
onEnter();
} else {
onExit();
}
}
@LayoutRes
protected abstract int getLayoutId();
protected abstract Toolbar getToolbar();
protected View getStatusView() {
return null;
}
protected abstract void initView(Bundle bundle);
protected abstract void initData(Bundle savedInstanceState);
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
fitsLayoutOverlap();
}
protected boolean isImmersionBarEnabled() {
return true;
}
protected boolean initStatusBarToolBar() {
return true;
}
private void fitsLayoutOverlap() {
if (!isImmersionBarEnabled()) return;
if (statusBarView != null) {
// ImmersionBar.setStatusBarView(getActivity(), statusBarView);
}
if (toolbar != null) {
// ImmersionBar.setTitleBar(getActivity(), toolbar);
}
}
protected void hideInputMethod(Activity activity) {
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
View view = activity.getCurrentFocus();
if (view != null) {
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
protected void hideInputMethod(Activity activity, EditText editText) {
InputMethodManager imm = (InputMethodManager) editText.getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
View view = activity.getCurrentFocus();
if (view != null) {
imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
protected void showInputMethod(EditText editText) {
InputMethodManager imm = (InputMethodManager) editText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED);
}
/**
* 進入界面
*/
protected void onEnter() {
}
/**
* 離開界面
*/
protected void onExit() {
}
private final BehaviorSubject<FragmentEvent> lifecycleSubject = BehaviorSubject.create();
public BehaviorSubject<FragmentEvent> getLifecycleSubject() {
return lifecycleSubject;
}
@Override
@NonNull
@CheckResult
public final Observable<FragmentEvent> lifecycle() {
return lifecycleSubject.hide();
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull FragmentEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindFragment(lifecycleSubject);
}
@Override
@CallSuper
public void onAttach(Activity activity) {
super.onAttach(activity);
lifecycleSubject.onNext(FragmentEvent.ATTACH);
}
@Override
@CallSuper
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleSubject.onNext(FragmentEvent.CREATE);
}
@Override
@CallSuper
public void onStart() {
super.onStart();
lifecycleSubject.onNext(FragmentEvent.START);
}
@Override
@CallSuper
public void onResume() {
super.onResume();
lifecycleSubject.onNext(FragmentEvent.RESUME);
}
@Override
@CallSuper
public void onPause() {
lifecycleSubject.onNext(FragmentEvent.PAUSE);
super.onPause();
}
@Override
@CallSuper
public void onStop() {
lifecycleSubject.onNext(FragmentEvent.STOP);
super.onStop();
}
@Override
@CallSuper
public void onDestroy() {
lifecycleSubject.onNext(FragmentEvent.DESTROY);
super.onDestroy();
}
@Override
@CallSuper
public void onDetach() {
lifecycleSubject.onNext(FragmentEvent.DETACH);
super.onDetach();
}
}

View File

@@ -0,0 +1,281 @@
package com.xxpatx.os.base.mvvm.fragment;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import com.xxpatx.os.base.BaseFragment;
import java.lang.ref.WeakReference;
import java.lang.reflect.ParameterizedType;
/**
* @author: lml
* @date: 2021/12/15
*/
public abstract class BaseMvvmFragment<VM extends ViewModel, VDB extends ViewDataBinding> extends BaseFragment {
protected String TAG = this.getClass().getSimpleName();
/**
* 是否顯示了
*/
protected boolean mIsVisible;
/**
* 是否準備好了-Created
*/
protected boolean mHasPrepare;
protected VM mViewModel;
protected VDB mViewDataBinding;
protected Class<VM> vmClass;
//
// protected Toolbar toolbar;
// protected View statusBarView;
//
protected Bundle bundle;//来自getArguments()
protected Bundle savedInstanceState;
// protected Context context;
/**
* 上下文
*/
private WeakReference<Context> ctx;
public Context getCtx() {
return ctx == null ? null : ctx.get();
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
// this.context = context;
Log.e(TAG, "onAttach: ");
ctx = new WeakReference<>(context);
}
/**
* onCreate、onResume里不能调用
*
* @return
*/
public boolean isAttached() {
boolean flag = getCtx() != null && isAdded();
Log.e(" >> isAttached >>", "flag = " + flag);
return flag;
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
Log.e(TAG, "onCreateView: ");
//ViewDataBinding
mViewDataBinding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false);
mViewDataBinding.setLifecycleOwner(this);
//ViewModel
vmClass = (Class<VM>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];
mViewModel = new ViewModelProvider(this).get(vmClass);
//
return mViewDataBinding.getRoot();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Log.e(TAG, "onViewCreated: ");
// if (initStatusBarToolBar()) {
// toolbar = getToolbar();
// }
//注册eventbus
// if (getClass().isAnnotationPresent(BindEventBus.class))
// EventBusManager.register(this);
//
// fitsLayoutOverlap();
initDataBinding();
initView(bundle = getArguments());
//
initData(this.savedInstanceState = savedInstanceState);
//
if (mIsVisible) {
onEnter();
}
mHasPrepare = true;
//
// LiveDataBus.get().with(ConstantUtils.DATA_BUS_LOADING_FRAGMENT, Boolean.class).observe(getActivity(), bool -> {
// L.e(" >> LiveDataBus >> DATA_BUS_LOADING_FRAGMENT: %s", bool);
// if(bool) {
// showLoading(R.string.str_please_wait);
// } else {
// hideLoading();
// }
// });
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.e(TAG, "onDestroyView: ");
mHasPrepare = false;
mViewDataBinding = null;
//移除eventbus
// if (getClass().isAnnotationPresent(BindEventBus.class))
// EventBusManager.unregister(this);
//
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
Log.e(TAG, "setUserVisibleHint: ");
if (mIsVisible == getUserVisibleHint())
return;
mIsVisible = getUserVisibleHint();
if (mIsVisible) {
if (!mHasPrepare)
return;
onEnter();
} else {
onExit();
}
}
@LayoutRes
protected abstract int getLayoutId();
// protected abstract Toolbar getToolbar();
// protected View getStatusView() {
// return null;
// }
protected abstract void initDataBinding();
protected abstract void initView(Bundle bundle);
protected abstract void initData(Bundle savedInstanceState);
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.e(TAG, "onConfigurationChanged: ");
// fitsLayoutOverlap();
}
// protected boolean isImmersionBarEnabled() {
// return true;
// }
// protected boolean initStatusBarToolBar() {
// return true;
// }
// private void fitsLayoutOverlap() {
// if (!isImmersionBarEnabled()) return;
// if (statusBarView != null) {
// ImmersionBar.setStatusBarView(getActivity(), statusBarView);
// }
// if (toolbar != null) {
// ImmersionBar.setTitleBar(getActivity(), toolbar);
// }
// }
protected void hideInputMethod(Activity activity) {
InputMethodManager imm = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
View view = activity.getCurrentFocus();
if (view != null) {
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}
protected void hideInputMethod(Activity activity, EditText editText) {
InputMethodManager imm = (InputMethodManager) editText.getContext().getSystemService(Activity.INPUT_METHOD_SERVICE);
View view = activity.getCurrentFocus();
if (view != null) {
imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
}
protected void showInputMethod(EditText editText) {
InputMethodManager imm = (InputMethodManager) editText.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showSoftInput(editText, InputMethodManager.SHOW_FORCED);
}
// private CustomDialog mWaitDialog;
//
// public void showLoading(@StringRes int contentID) {
// showLoading(contentID, R.color.white);
// }
//
// public void showLoading(@StringRes int contentID, @ColorRes int color) {
// hideLoading();
// DialogX.init(getActivity());
// if (color == R.color.white) {
// mWaitDialog = DialogXUtil.getInstance().showLoading(getActivity(), getString(contentID), getResources().getColor(color));
// } else {
// mWaitDialog = DialogXUtil.getInstance().showLoading_black(getActivity(), getString(contentID), getResources().getColor(color));
// }
// }
//
// public void updateLoadingTip(@StringRes int messageID, int percent) {
// try {
// if (mWaitDialog != null && mWaitDialog.isShow()) {
// TextView tvTip = mWaitDialog.getCustomView().findViewById(R.id.tv_load_tip);
// if (tvTip != null)
// tvTip.setText(getResources().getString(messageID) + (percent == -1 ? "" : percent + "%"));
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
//
// public boolean isShowLoading() {
// return mWaitDialog != null && mWaitDialog.isShow();
// }
//
// public void hideLoading() {
// try {
// boolean isShow = isShowLoading();
// L.d(" >> hideLoading :: isShow: %s", isShow);
// if (isShow)
// mWaitDialog.dismiss();
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
/**
* 進入界面
*/
protected void onEnter() {
}
/**
* 離開界面
*/
protected void onExit() {
}
}

View File

@@ -0,0 +1,94 @@
package com.xxpatx.os.base.rx;
import android.os.Bundle;
import androidx.annotation.CallSuper;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.trello.rxlifecycle4.LifecycleProvider;
import com.trello.rxlifecycle4.LifecycleTransformer;
import com.trello.rxlifecycle4.RxLifecycle;
import com.trello.rxlifecycle4.android.ActivityEvent;
import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
/**
* {@link com.trello.rxlifecycle4.components.RxActivity}
* copied form RxActivity}
*/
public abstract class BaseRxActivity extends AppCompatActivity implements LifecycleProvider<ActivityEvent> {
private final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
public BehaviorSubject<ActivityEvent> getLifecycleSubject() {
return lifecycleSubject;
}
@Override
@NonNull
@CheckResult
public final Observable<ActivityEvent> lifecycle() {
return lifecycleSubject.hide();
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(lifecycleSubject);
}
@Override
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleSubject.onNext(ActivityEvent.CREATE);
}
@Override
@CallSuper
protected void onStart() {
super.onStart();
lifecycleSubject.onNext(ActivityEvent.START);
}
@Override
@CallSuper
protected void onResume() {
super.onResume();
lifecycleSubject.onNext(ActivityEvent.RESUME);
}
@Override
@CallSuper
protected void onPause() {
lifecycleSubject.onNext(ActivityEvent.PAUSE);
super.onPause();
}
@Override
@CallSuper
protected void onStop() {
lifecycleSubject.onNext(ActivityEvent.STOP);
super.onStop();
}
@Override
@CallSuper
protected void onDestroy() {
lifecycleSubject.onNext(ActivityEvent.DESTROY);
super.onDestroy();
}
}

View File

@@ -0,0 +1,123 @@
package com.xxpatx.os.base.rx;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.CallSuper;
import androidx.annotation.CheckResult;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.trello.rxlifecycle4.LifecycleProvider;
import com.trello.rxlifecycle4.LifecycleTransformer;
import com.trello.rxlifecycle4.RxLifecycle;
import com.trello.rxlifecycle4.android.FragmentEvent;
import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
/**
* {@link com.trello.rxlifecycle4.components.RxFragment}
* copied form RxFragment}
*/
public class BaseRxFragment extends Fragment implements LifecycleProvider<FragmentEvent> {
private final BehaviorSubject<FragmentEvent> lifecycleSubject = BehaviorSubject.create();
public BehaviorSubject<FragmentEvent> getLifecycleSubject() {
return lifecycleSubject;
}
@Override
@NonNull
@CheckResult
public final Observable<FragmentEvent> lifecycle() {
return lifecycleSubject.hide();
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull FragmentEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
@Override
@NonNull
@CheckResult
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindFragment(lifecycleSubject);
}
@Override
@CallSuper
public void onAttach(android.app.Activity activity) {
super.onAttach(activity);
lifecycleSubject.onNext(FragmentEvent.ATTACH);
}
@Override
@CallSuper
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
lifecycleSubject.onNext(FragmentEvent.CREATE);
}
@Override
@CallSuper
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
lifecycleSubject.onNext(FragmentEvent.CREATE_VIEW);
}
@Override
@CallSuper
public void onStart() {
super.onStart();
lifecycleSubject.onNext(FragmentEvent.START);
}
@Override
@CallSuper
public void onResume() {
super.onResume();
lifecycleSubject.onNext(FragmentEvent.RESUME);
}
@Override
@CallSuper
public void onPause() {
lifecycleSubject.onNext(FragmentEvent.PAUSE);
super.onPause();
}
@Override
@CallSuper
public void onStop() {
lifecycleSubject.onNext(FragmentEvent.STOP);
super.onStop();
}
@Override
@CallSuper
public void onDestroyView() {
lifecycleSubject.onNext(FragmentEvent.DESTROY_VIEW);
super.onDestroyView();
}
@Override
@CallSuper
public void onDestroy() {
lifecycleSubject.onNext(FragmentEvent.DESTROY);
super.onDestroy();
}
@Override
@CallSuper
public void onDetach() {
lifecycleSubject.onNext(FragmentEvent.DETACH);
super.onDetach();
}
}

View File

@@ -0,0 +1,56 @@
package com.xxpatx.os.base.rx;
import android.app.Service;
import android.content.Intent;
import androidx.annotation.NonNull;
import com.trello.rxlifecycle4.LifecycleProvider;
import com.trello.rxlifecycle4.LifecycleTransformer;
import com.trello.rxlifecycle4.RxLifecycle;
import com.trello.rxlifecycle4.android.ActivityEvent;
import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.BehaviorSubject;
public abstract class BaseRxService extends Service implements LifecycleProvider<ActivityEvent> {
public final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
public BaseRxService() {
super();
}
@Override
public final Observable<ActivityEvent> lifecycle() {
return lifecycleSubject.hide();
}
@Override
public final <T> LifecycleTransformer<T> bindUntilEvent(@NonNull ActivityEvent event) {
return RxLifecycle.bindUntilEvent(lifecycleSubject, event);
}
@Override
public final <T> LifecycleTransformer<T> bindToLifecycle() {
return RxLifecycleAndroid.bindActivity(lifecycleSubject);
}
@Override
public void onCreate() {
super.onCreate();
lifecycleSubject.onNext(ActivityEvent.CREATE);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
lifecycleSubject.onNext(ActivityEvent.STOP);
}
}