futureList = new ArrayList<>();
+
+ /**
+ * P层
+ */
+ protected P p;
+
+ /**
+ * CommonToolBar
+ */
+ protected CommonToolBar toolBar;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ ActivityManager.getInstance().pushActivity(this);
+ createTime = System.currentTimeMillis();
+ method = "onCreate";
+ super.onCreate(savedInstanceState);
+ setContentView(getContentViewResId());
+ toolBar = searchToolBar(findViewById(android.R.id.content));
+ initView();
+ initData();
+ }
+
+ /**
+ * 获取布局
+ */
+ protected abstract int getContentViewResId();
+
+ /**
+ * 初始化P层
+ */
+ protected void initPresnter() {
+ p = getInstanceP();
+ if (p != null) {
+ p.attachView(this);
+ }
+ }
+
+
+ /**
+ * 查找是否有CommonToolBar
+ *
+ * @param viewGroup
+ * @return
+ */
+ private CommonToolBar searchToolBar(ViewGroup viewGroup) {
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ View v = viewGroup.getChildAt(i);
+ if (v instanceof CommonToolBar) {
+ return (CommonToolBar) v;
+ } else if (v instanceof ViewGroup) {
+ View view = searchToolBar((ViewGroup) v);
+ if (view instanceof CommonToolBar) {
+ return (CommonToolBar) view;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 创建泛型实例
+ */
+ private P getInstanceP() {
+ try {
+ Type superclass = getClass().getGenericSuperclass();
+ ParameterizedType parameterizedType = null;
+ if (superclass instanceof ParameterizedType) {
+ parameterizedType = (ParameterizedType) superclass;
+ Type[] typeArray = parameterizedType.getActualTypeArguments();
+ if (typeArray != null && typeArray.length > 0) {
+ Class clazz = (Class
) typeArray[0];
+ return clazz.newInstance();
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ } catch (Exception e) {
+ Log.e("genericity error", e.toString());
+ return null;
+ }
+ }
+
+ /**
+ * 初始布局
+ */
+ protected abstract void initView();
+
+ /**
+ * 初始数据
+ */
+ protected abstract void initData();
+
+ @Override
+ public void setContentView(@LayoutRes int layoutResID) {
+ super.setContentView(layoutResID);
+ }
+
+ @Override
+ public void setContentView(View view) {
+ super.setContentView(view);
+ }
+
+
+ @Override
+ public void setContentView(View view, ViewGroup.LayoutParams params) {
+ super.setContentView(view, params);
+ }
+
+ @Override
+ protected void onDestroy() {
+ stopCurrentThread();
+ getExecutor().stop(futureList);
+ super.onDestroy();
+ if (p != null) {
+ p.detachView();
+ p = null;
+ }
+ ActivityManager.getInstance().popActivity(this);
+ }
+
+ @Override
+ protected void onResume() {
+ if (createTime == 0) {
+ method = "onResume";
+ createTime = System.currentTimeMillis();
+ }
+ super.onResume();
+ }
+
+ @Override
+ protected void onRestart() {
+ createTime = System.currentTimeMillis();
+ method = "onRestart";
+ super.onRestart();
+ }
+
+ @Override
+ public LifecycleTransformer bindRecycler() {
+ LifecycleTransformer objectLifecycleTransformer = bindToLifecycle();
+ return objectLifecycleTransformer;
+ }
+
+ protected Pool getExecutor() {
+ return BaseApplication.getInstance().getExecutor();
+ }
+
+
+ protected TaskBean execute(Runnable runnable) {
+ return ThreadManager.getInstance().execute(this, runnable);
+ }
+
+ protected TaskBean execute(int delay, Runnable runnable) {
+ return ThreadManager.getInstance().execute(this, delay, runnable);
+ }
+
+ protected TaskBean execute(@NonNull Callable callable, AsyncCallback callback) {
+ return ThreadManager.getInstance().execute(this, callable, callback);
+ }
+
+
+ protected TaskBean execute(int delay, @NonNull Callable callable, AsyncCallback callback) {
+ return ThreadManager.getInstance().execute(this, delay, callable, callback);
+ }
+
+ protected void stopCurrentThread() {
+ ThreadManager.getInstance().remove(this);
+ }
+}
diff --git a/libs/src/main/java/com/libs/fragment/BaseApplication.java b/libs/src/main/java/com/libs/fragment/BaseApplication.java
new file mode 100644
index 0000000..10425ae
--- /dev/null
+++ b/libs/src/main/java/com/libs/fragment/BaseApplication.java
@@ -0,0 +1,104 @@
+package com.libs.fragment;
+
+import android.app.ActivityManager;
+import android.app.Application;
+import android.content.Context;
+
+
+import com.libs.threadpool.Pool;
+import com.libs.threadpool.Type;
+import com.libs.threadpool.callback.DefLogCallBack;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+
+
+/**
+ * @author Ming
+ * 1/12/21
+ */
+public abstract class BaseApplication extends Application {
+
+ protected Pool pool;
+ private static BaseApplication baseApplication = null;
+
+ public static BaseApplication getInstance() {
+ return baseApplication;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ baseApplication = this;
+ }
+
+ /**
+ * 初始化线程池
+ */
+ protected void initThreadPool(@Type int type) {
+ pool = new Pool.Builder()
+ .setThreadType(type)
+ .setLog(new DefLogCallBack())
+ .build();
+ }
+
+
+ /**
+ * 获取线程池
+ *
+ * @return
+ */
+ public Pool getExecutor() {
+ if (pool == null) {
+ initThreadPool(Type.FIXED);
+ }
+ return pool;
+ }
+
+ /**
+ * 判断当前进程是否为主进程
+ *
+ * @return
+ */
+ private boolean isMainProcess() {
+ int pid = android.os.Process.myPid();
+ String processName = "";
+ ActivityManager mActivityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
+ for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager.getRunningAppProcesses()) {
+ if (appProcess.pid == pid) {
+ processName = appProcess.processName;
+ break;
+ }
+ }
+ String packageName = this.getPackageName();
+ if (processName.equals(packageName)) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
+ try {
+ Field field = getClass().getSuperclass().getSuperclass().getDeclaredField("mActivityLifecycleCallbacks");
+ field.setAccessible(true);
+ ArrayList activityLifecycleCallbacks = (ArrayList) field.get(this);
+ boolean contain = false;
+ for (ActivityLifecycleCallbacks activityLifecycleCallback : activityLifecycleCallbacks) {
+ if (activityLifecycleCallback.getClass().equals(callback.getClass())) {
+ contain = true;
+ }
+ }
+ if (!contain) {
+ super.registerActivityLifecycleCallbacks(callback);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected boolean showMonitor() {
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/libs/src/main/java/com/libs/fragment/BaseFragment.java b/libs/src/main/java/com/libs/fragment/BaseFragment.java
new file mode 100644
index 0000000..7a3330d
--- /dev/null
+++ b/libs/src/main/java/com/libs/fragment/BaseFragment.java
@@ -0,0 +1,114 @@
+package com.libs.fragment;
+
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.Nullable;
+
+
+import com.trello.rxlifecycle4.LifecycleTransformer;
+import com.trello.rxlifecycle4.components.RxFragment;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+
+/**
+ * Created by Ming
+ * 2020-09-09
+ */
+public abstract class BaseFragment extends RxFragment implements BaseView {
+ private View mRootView;
+ private P p;
+
+
+ @Nullable
+ @Override
+ public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
+ if (mRootView == null) {
+ mRootView = inflater.inflate(getLayoutId(), container, false);
+ }
+ ViewGroup parent = (ViewGroup) mRootView.getParent();
+ if (parent != null) {
+ parent.removeView(mRootView);
+ }
+ return mRootView;
+ }
+
+ @Override
+ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ initView(view, savedInstanceState);
+ initData();
+ }
+
+ /**
+ * 获取布局
+ */
+ protected abstract int getLayoutId();
+
+ /**
+ * 初始布局
+ */
+ protected abstract void initView(View view, Bundle savedInstanceState);
+
+ /**
+ * 初始数据
+ */
+ protected abstract void initData();
+
+ /**
+ * 初始p层
+ */
+ protected void initPresnter() {
+ p = getInstanceP();
+ if (p != null) {
+ p.attachView(this);
+ }
+ }
+
+ /**
+ * 创建泛型实例
+ */
+ private P getInstanceP() {
+ try {
+ Type superclass = getClass().getGenericSuperclass();
+ ParameterizedType parameterizedType = null;
+ if (superclass instanceof ParameterizedType) {
+ parameterizedType = (ParameterizedType) superclass;
+ Type[] typeArray = parameterizedType.getActualTypeArguments();
+ if (typeArray != null && typeArray.length > 0) {
+ Class
clazz = (Class
) typeArray[0];
+ return clazz.newInstance();
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ } catch (Exception e) {
+ Log.e("泛型创建错误", e.toString());
+ return null;
+ }
+ }
+
+ @Override
+ public LifecycleTransformer bindRecycler() {
+ return this.bindToLifecycle();
+ }
+
+
+ @Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (p != null) {
+ p.detachView();
+ p = null;
+ }
+ }
+}
+
diff --git a/libs/src/main/java/com/libs/fragment/BasePresenter.java b/libs/src/main/java/com/libs/fragment/BasePresenter.java
new file mode 100644
index 0000000..678d110
--- /dev/null
+++ b/libs/src/main/java/com/libs/fragment/BasePresenter.java
@@ -0,0 +1,31 @@
+package com.libs.fragment;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * @author Ming
+ * 1/11/21
+ * P层基类
+ */
+public class BasePresenter {
+ protected V v;
+ private WeakReference mViewRef;
+
+ public BasePresenter() {
+
+ }
+
+ protected void attachView(V view) {
+ mViewRef = new WeakReference<>(view);
+ v = mViewRef != null ? mViewRef.get() : null;
+ }
+
+
+ protected void detachView() {
+ if (mViewRef != null) {
+ mViewRef.clear();
+ }
+ mViewRef = null;
+ v = null;
+ }
+}
diff --git a/libs/src/main/java/com/libs/fragment/BaseView.java b/libs/src/main/java/com/libs/fragment/BaseView.java
new file mode 100644
index 0000000..bd3c4ea
--- /dev/null
+++ b/libs/src/main/java/com/libs/fragment/BaseView.java
@@ -0,0 +1,13 @@
+package com.libs.fragment;
+
+
+import com.trello.rxlifecycle4.LifecycleTransformer;
+
+/**
+ * @author Ming
+ * 1/11/21
+ * V层基类
+ */
+public interface BaseView {
+ LifecycleTransformer bindRecycler();
+}
diff --git a/libs/src/main/java/com/libs/network/CallBack.java b/libs/src/main/java/com/libs/network/CallBack.java
new file mode 100644
index 0000000..22f04a3
--- /dev/null
+++ b/libs/src/main/java/com/libs/network/CallBack.java
@@ -0,0 +1,19 @@
+package com.libs.network;
+
+
+/**
+ * Created by Ming
+ * 2020-09-08
+ */
+public interface CallBack{
+ /**
+ * 成功
+ */
+ void onSuccess(K k);
+
+ /**
+ * 失败
+ */
+ void onFailed(Throwable e);
+
+}
diff --git a/libs/src/main/java/com/libs/network/Concise.java b/libs/src/main/java/com/libs/network/Concise.java
new file mode 100644
index 0000000..e0e1945
--- /dev/null
+++ b/libs/src/main/java/com/libs/network/Concise.java
@@ -0,0 +1,223 @@
+package com.libs.network;
+
+import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentActivity;
+
+import com.libs.network.interceptor.ErrCodeInterceptor;
+import com.libs.network.interceptor.ErrorCodeCallBack;
+import com.libs.network.interceptor.HeaderInterceptor;
+import com.trello.rxlifecycle4.components.RxActivity;
+import com.trello.rxlifecycle4.components.RxFragment;
+
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+
+import autodispose2.AutoDispose;
+import autodispose2.androidx.lifecycle.AndroidLifecycleScopeProvider;
+import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
+import io.reactivex.rxjava3.annotations.NonNull;
+import io.reactivex.rxjava3.core.Observable;
+import io.reactivex.rxjava3.core.Observer;
+import io.reactivex.rxjava3.schedulers.Schedulers;
+import okhttp3.Interceptor;
+import okhttp3.OkHttpClient;
+import okhttp3.logging.HttpLoggingInterceptor;
+import retrofit2.Retrofit;
+import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+
+/**
+ * @author Ming
+ * 1/20/22
+ */
+public class Concise {
+ public I api;
+ private String path;
+ private Executor executor;
+ private boolean showLog = true;
+ private List interceptorList = new ArrayList<>();
+ private Map headMap = new HashMap<>();
+
+ public Concise(String path) {
+ this.path = path;
+ }
+
+ public Concise addHeader(String key, String value) {
+ headMap.put(key, value);
+ return this;
+ }
+
+ public Map getHeadMap() {
+ return headMap;
+ }
+
+ public Concise setToken(String token) {
+ headMap.put("Authorization", token);
+ return this;
+ }
+
+ public Concise setPath(String path) {
+ this.path = path;
+ return this;
+ }
+
+ public Concise showLog(boolean b) {
+ showLog = b;
+ return this;
+ }
+
+ public Concise setThreadPool(Executor executor) {
+ this.executor = executor;
+ return this;
+ }
+
+ public Concise addInterceptors(Interceptor... interceptors) {
+ for (Interceptor interceptor : interceptors) {
+ interceptorList.add(interceptor);
+ }
+ return this;
+ }
+
+ public Concise setErrCodeListener(String errCode, String tokenKey, ErrorCodeCallBack tokenCallBack) {
+ interceptorList.add(new ErrCodeInterceptor(errCode, tokenKey, tokenCallBack));
+ return this;
+ }
+
+ public String getPath() {
+ return path;
+ }
+
+
+ public Concise build() {
+ Class tClass = (Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
+ api = new Retrofit.Builder()
+ .client(createClient())
+ .addConverterFactory(GsonConverterFactory.create())
+ .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
+ .baseUrl(path)
+ .build()
+ .create(tClass);
+ return this;
+ }
+
+ public void request(Observable observable, @NonNull CallBack callBack) {
+ if (callBack != null && observable != null) {
+ initObservable(observable)
+ .subscribe(new DefaultObserver(callBack));
+ }
+ }
+
+ public void request(Fragment fragment, Observable observable, @NonNull CallBack callBack) {
+ if (callBack != null && observable != null) {
+ initObservable(observable)
+ .to(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(fragment)))
+ .subscribe(new DefaultObserver(callBack));
+ }
+ }
+
+ public void request(RxFragment rxFragment, Observable observable, @NonNull CallBack callBack) {
+ if (callBack != null && observable != null) {
+ initObservable(observable)
+ .compose(rxFragment.bindToLifecycle())
+ .subscribe(new DefaultObserver(callBack));
+ }
+ }
+
+ public void request(FragmentActivity activity, Observable observable, @NonNull CallBack callBack) {
+ if (callBack != null && observable != null) {
+ initObservable(observable)
+ .to(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(activity)))
+ .subscribe(new DefaultObserver(callBack));
+ }
+ }
+
+ public void request(RxActivity rxActivity, Observable observable, @NonNull CallBack callBack) {
+ if (callBack != null && observable != null) {
+ initObservable(observable)
+ .compose(rxActivity.bindToLifecycle())
+ .subscribe(new DefaultObserver(callBack));
+ }
+ }
+
+ public void request(Observable observable, @NonNull Observer observer) {
+ if (observer != null) {
+ initObservable(observable)
+ .subscribe(observer);
+ }
+ }
+
+ public void request(Fragment fragment, Observable observable, @NonNull Observer observer) {
+ if (observer != null) {
+ initObservable(observable)
+ .to(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(fragment)))
+ .subscribe(observer);
+ }
+ }
+
+ public void request(RxFragment rxFragment, Observable observable, @NonNull Observer observer) {
+ if (observer != null) {
+ initObservable(observable)
+ .compose(rxFragment.bindToLifecycle())
+ .subscribe(observer);
+ }
+ }
+
+ public void request(FragmentActivity activity, Observable observable, @NonNull Observer observer) {
+ if (observer != null) {
+ initObservable(observable)
+ .to(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(activity)))
+ .subscribe(observer);
+ }
+ }
+
+ public void request(RxActivity rxActivity, Observable observable, @NonNull Observer observer) {
+ if (observer != null) {
+ initObservable(observable)
+ .compose(rxActivity.bindToLifecycle())
+ .subscribe(observer);
+ }
+ }
+
+ private Observable initObservable(Observable observable) {
+ if (executor == null) {
+ return observable
+ .delay(5, TimeUnit.MILLISECONDS)
+ .subscribeOn(Schedulers.io())
+ .unsubscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread());
+ }
+ return observable
+ .subscribeOn(Schedulers.from(executor))
+ .unsubscribeOn(Schedulers.from(executor))
+ .observeOn(AndroidSchedulers.mainThread());
+ }
+
+
+ public OkHttpClient createClient() {
+ OkHttpClient.Builder builder = new OkHttpClient.Builder();
+ //添加拦截器获取log
+ if (showLog) {
+ HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
+ logging.setLevel(HttpLoggingInterceptor.Level.BODY);
+ builder.addInterceptor(logging);
+ for (Interceptor interceptor : interceptorList) {
+ builder.addInterceptor(interceptor);
+ }
+ }
+ if (headMap.size() > 0) {
+ builder.addInterceptor(new HeaderInterceptor(headMap));
+ }
+ builder.dns(new HttpDns());
+// builder.connectTimeout(outTime, TimeUnit.SECONDS);
+// builder.readTimeout(outTime, TimeUnit.SECONDS);
+// builder.writeTimeout(outTime, TimeUnit.SECONDS);
+// builder.addInterceptor(new TokenInterceptor(tokenKey, token));
+ return builder.build();
+ }
+}
diff --git a/libs/src/main/java/com/libs/network/DefaultObserver.java b/libs/src/main/java/com/libs/network/DefaultObserver.java
new file mode 100644
index 0000000..071fafd
--- /dev/null
+++ b/libs/src/main/java/com/libs/network/DefaultObserver.java
@@ -0,0 +1,37 @@
+package com.libs.network;
+
+import io.reactivex.rxjava3.annotations.NonNull;
+import io.reactivex.rxjava3.core.Observer;
+import io.reactivex.rxjava3.disposables.Disposable;
+
+/**
+ * @author Ming
+ * 2/23/22
+ */
+public class DefaultObserver implements Observer {
+ private CallBack callBack;
+
+
+ public DefaultObserver(@NonNull CallBack callBack) {
+ this.callBack = callBack;
+ }
+
+ @Override
+ public void onSubscribe(@NonNull Disposable d) {
+ }
+
+ @Override
+ public void onNext(@NonNull S s) {
+ callBack.onSuccess(s);
+ }
+
+ @Override
+ public void onError(@NonNull Throwable e) {
+ callBack.onFailed(e);
+ }
+
+ @Override
+ public void onComplete() {
+
+ }
+}
diff --git a/libs/src/main/java/com/libs/network/HttpDns.java b/libs/src/main/java/com/libs/network/HttpDns.java
new file mode 100644
index 0000000..0c36a1c
--- /dev/null
+++ b/libs/src/main/java/com/libs/network/HttpDns.java
@@ -0,0 +1,68 @@
+package com.libs.network;
+
+import com.qiniu.android.dns.DnsManager;
+import com.qiniu.android.dns.IResolver;
+import com.qiniu.android.dns.NetworkInfo;
+import com.qiniu.android.dns.local.Resolver;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+
+import okhttp3.Dns;
+
+import static java.net.InetAddress.getAllByName;
+import static java.net.InetAddress.getByName;
+
+/**
+ * @author Ming
+ * 7/27/21
+ */
+public class HttpDns implements Dns {
+ private DnsManager dnsManager;
+
+ public HttpDns() {
+ IResolver[] resolvers = new IResolver[1];
+ try {
+ resolvers[0] = new Resolver(getByName("119.29.29.29"));
+ dnsManager = new DnsManager(NetworkInfo.normal, resolvers);
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public List lookup(String hostname) throws UnknownHostException {
+ if (dnsManager == null) {
+ return Dns.SYSTEM.lookup(hostname);
+ }
+
+ try {
+ String[] ips = dnsManager.query(hostname);
+ if (ips == null || ips.length == 0) {
+ return Dns.SYSTEM.lookup(hostname);
+ }
+ FutureTask> task = new FutureTask<>(
+ new Callable>() {
+ @Override
+ public List call() throws Exception {
+ List result = new ArrayList<>();
+ for (String ip : ips) {
+ result.addAll(Arrays.asList(getAllByName(ip)));
+ }
+ return result;
+ }
+ });
+ new Thread(task).start();
+ return task.get(5000, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return Dns.SYSTEM.lookup(hostname);
+ }
+}
\ No newline at end of file
diff --git a/libs/src/main/java/com/libs/network/interceptor/ErrCodeInterceptor.java b/libs/src/main/java/com/libs/network/interceptor/ErrCodeInterceptor.java
new file mode 100644
index 0000000..00c9f26
--- /dev/null
+++ b/libs/src/main/java/com/libs/network/interceptor/ErrCodeInterceptor.java
@@ -0,0 +1,59 @@
+package com.libs.network.interceptor;
+
+import android.text.TextUtils;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+
+import okhttp3.Interceptor;
+import okhttp3.MediaType;
+import okhttp3.Request;
+import okhttp3.Response;
+import okhttp3.ResponseBody;
+import okio.Buffer;
+import okio.BufferedSource;
+
+/**
+ * @author Ming
+ * 3/2/22
+ */
+public class ErrCodeInterceptor implements Interceptor {
+ private String errCode;
+ private String tokenKey;
+ private ErrorCodeCallBack tokenCallBack;
+ private static final Charset UTF8 = Charset.forName("UTF-8");
+
+ public ErrCodeInterceptor(String errCode, String tokenKey, ErrorCodeCallBack tokenCallBack) {
+ this.errCode = errCode;
+ this.tokenKey = tokenKey;
+ this.tokenCallBack = tokenCallBack;
+ }
+
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+ Request request = chain.request();
+ Response originalResponse = chain.proceed(request);
+ ResponseBody responseBody = originalResponse.body();
+ BufferedSource source = responseBody.source();
+ source.request(Long.MAX_VALUE);
+ Buffer buffer = source.buffer();
+ Charset charset = UTF8;
+ MediaType contentType = responseBody.contentType();
+ if (contentType != null) {
+ charset = contentType.charset(UTF8);
+ }
+ String bodyString = buffer.clone().readString(charset);
+ if (bodyString.contains(errCode)) {
+ String newToken = tokenCallBack.token();
+ if (TextUtils.isEmpty(newToken)) {
+ return originalResponse;
+ }
+ Request newRequest = request.newBuilder().header(tokenKey, newToken).build();
+ originalResponse.body().close();
+ return chain.proceed(newRequest);
+ }
+ return originalResponse;
+ }
+}
+
+
diff --git a/libs/src/main/java/com/libs/network/interceptor/ErrorCodeCallBack.java b/libs/src/main/java/com/libs/network/interceptor/ErrorCodeCallBack.java
new file mode 100644
index 0000000..832892c
--- /dev/null
+++ b/libs/src/main/java/com/libs/network/interceptor/ErrorCodeCallBack.java
@@ -0,0 +1,9 @@
+package com.libs.network.interceptor;
+
+/**
+ * @author Ming
+ * 3/2/22
+ */
+public interface ErrorCodeCallBack {
+ String token();
+}
diff --git a/libs/src/main/java/com/libs/network/interceptor/HeaderInterceptor.java b/libs/src/main/java/com/libs/network/interceptor/HeaderInterceptor.java
new file mode 100644
index 0000000..bb7e32a
--- /dev/null
+++ b/libs/src/main/java/com/libs/network/interceptor/HeaderInterceptor.java
@@ -0,0 +1,32 @@
+package com.libs.network.interceptor;
+
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Map;
+
+import okhttp3.Interceptor;
+import okhttp3.Request;
+import okhttp3.Response;
+
+
+public class HeaderInterceptor implements Interceptor {
+ private Map map;
+
+ public HeaderInterceptor(Map map) {
+ this.map = map;
+ }
+
+ @Override
+ public Response intercept(Chain chain) throws IOException {
+ Request.Builder builder = chain.request().newBuilder();
+ Iterator> entries = map.entrySet().iterator();
+ while (entries.hasNext()) {
+ Map.Entry entry = entries.next();
+ if (entry != null) {
+ builder.addHeader(entry.getKey(),entry.getValue());
+ }
+ }
+ Request interRequest = builder.build();
+ return chain.proceed(interRequest);
+ }
+}
diff --git a/libs/src/main/java/com/libs/threadpool/Pool.java b/libs/src/main/java/com/libs/threadpool/Pool.java
new file mode 100644
index 0000000..d0da293
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/Pool.java
@@ -0,0 +1,143 @@
+package com.libs.threadpool;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.libs.threadpool.callback.AsyncCallback;
+import com.libs.threadpool.callback.OnTaskStart;
+import com.libs.threadpool.callback.ThreadCallback;
+import com.libs.utils.DataUtil;
+
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+
+/**
+ * @author Ming
+ * 1/13/21
+ */
+public class Pool {
+ /**
+ * 线程池类型
+ */
+ private int type;
+ private int size = 5;
+ private int time = 0;
+ private String defName = "DefThreadName";
+ private ThreadCallback defCallback;
+ private AsyncCallback defAsyncCallback;
+ private ExecutorService executorServicePool;
+ private ThreadLocal local;
+
+ public static class Builder {
+ private Pool pool;
+
+ public Builder() {
+ pool = new Pool();
+ }
+
+ public Builder setThreadType(@Type int type) {
+ pool.type = type;
+ return this;
+ }
+
+ public Builder setLog(ThreadCallback threadCallback) {
+ pool.defCallback = threadCallback;
+ return this;
+ }
+
+ public Builder setSize(int size) {
+ pool.size = size;
+ return this;
+ }
+
+ public Pool build() {
+ pool.local = new ThreadLocal<>();
+ pool.executorServicePool = pool.createThreadPool();
+ return pool;
+ }
+ }
+
+ public Pool setName(String name) {
+ defName = name;
+ return this;
+ }
+
+ public Pool setDelay(int time) {
+ this.time = time;
+ return this;
+ }
+
+ private synchronized ThreadConfigs getThreadConfigs() {
+ ThreadConfigs threadConfigs = local.get();
+ if (threadConfigs == null) {
+ threadConfigs = new ThreadConfigs();
+ threadConfigs.name = defName;
+ threadConfigs.callback = defCallback;
+ threadConfigs.asyncCallback = defAsyncCallback;
+ }
+ return threadConfigs;
+ }
+
+ public Future execute(Runnable runnable, OnTaskStart onTaskStart) {
+ ThreadConfigs configs = getThreadConfigs();
+ runnable = new RunnableWrapper(configs).setRunnable(runnable);
+ local.set(null);
+ return ThreadPoolInternal.getInstance().postDelay(time, executorServicePool, (RunnableWrapper) runnable, onTaskStart);
+ }
+
+ public Future execute(@NonNull Callable callable, AsyncCallback callback, OnTaskStart onTaskStart) {
+ ThreadConfigs configs = getThreadConfigs();
+ configs.asyncCallback = callback;
+ Runnable runnable = new RunnableWrapper(configs).setCallable(callable);
+ local.set(null);
+ return ThreadPoolInternal.getInstance().postDelay(time, executorServicePool, (RunnableWrapper) runnable, onTaskStart);
+ }
+
+ @Nullable
+ public Executor getThreadPool() {
+ return executorServicePool;
+ }
+
+ /**
+ * 暂停全部任务
+ */
+ public void stop() {
+ executorServicePool.shutdownNow();
+ }
+
+ /**
+ * 暂停任务
+ *
+ * @param futureList
+ */
+ public void stop(List futureList) {
+ if (!DataUtil.isNull(futureList)) {
+ for (Future future : futureList) {
+ if (future != null) {
+ future.cancel(true);
+ }
+ }
+ }
+ }
+
+
+ private synchronized ExecutorService createThreadPool() {
+ switch (type) {
+ case Type.CACHE:
+ return Executors.newCachedThreadPool();
+ case Type.FIXED:
+ return Executors.newFixedThreadPool(size);
+ case Type.SCHEDULED:
+ return Executors.newScheduledThreadPool(size);
+ case Type.SINGLE:
+ return Executors.newSingleThreadExecutor();
+ default:
+ return null;
+ }
+ }
+}
diff --git a/libs/src/main/java/com/libs/threadpool/RunnableWrapper.java b/libs/src/main/java/com/libs/threadpool/RunnableWrapper.java
new file mode 100644
index 0000000..aa58334
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/RunnableWrapper.java
@@ -0,0 +1,47 @@
+package com.libs.threadpool;
+
+import com.libs.threadpool.callback.MergeCallback;
+
+import java.util.concurrent.Callable;
+
+/**
+ * @author Ming
+ * 1/13/21
+ */
+public class RunnableWrapper implements Runnable {
+ private ThreadConfigs threadConfigs;
+ private MergeCallback mergeCallback;
+ private Runnable runnable;
+ private Callable callable;
+
+ public RunnableWrapper(ThreadConfigs threadConfigs) {
+ this.threadConfigs = threadConfigs;
+ mergeCallback = new MergeCallback(threadConfigs.callback, TranRunnable.getInstance(), threadConfigs.asyncCallback);
+ }
+
+ public RunnableWrapper setRunnable(Runnable runnable) {
+ this.runnable = runnable;
+ return this;
+ }
+
+ public RunnableWrapper setCallable(Callable callable) {
+ this.callable = callable;
+ return this;
+ }
+
+ @Override
+ public void run() {
+ mergeCallback.onStart(threadConfigs.name);
+ try {
+ if (runnable != null) {
+ runnable.run();
+ } else if (callable != null) {
+ Object result = callable.call();
+ mergeCallback.onSuccess(result);
+ }
+ mergeCallback.onCompleted(threadConfigs.name);
+ } catch (Exception e) {
+ mergeCallback.onError(threadConfigs.name, e);
+ }
+ }
+}
diff --git a/libs/src/main/java/com/libs/threadpool/TaskBean.java b/libs/src/main/java/com/libs/threadpool/TaskBean.java
new file mode 100644
index 0000000..aba0f14
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/TaskBean.java
@@ -0,0 +1,43 @@
+package com.libs.threadpool;
+
+import com.libs.utils.DataUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+
+
+/**
+ * @author Ming
+ * 7/29/21
+ */
+public class TaskBean {
+ private List futureList;
+
+ public TaskBean() {
+ futureList = new ArrayList<>();
+ }
+
+ public void addFuture(Future future) {
+ futureList.add(future);
+ }
+
+ public void removeFuture(Future future) {
+ futureList.remove(future);
+ }
+
+ public void stopTask() {
+ if (!DataUtil.isNull(futureList)) {
+ for (Future future : futureList) {
+ future.cancel(true);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "TaskBean{" +
+ "futureList=" + futureList.toString() +
+ '}';
+ }
+}
diff --git a/libs/src/main/java/com/libs/threadpool/ThreadConfigs.java b/libs/src/main/java/com/libs/threadpool/ThreadConfigs.java
new file mode 100644
index 0000000..e6328b3
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/ThreadConfigs.java
@@ -0,0 +1,32 @@
+package com.libs.threadpool;
+
+
+import com.libs.threadpool.callback.AsyncCallback;
+import com.libs.threadpool.callback.ThreadCallback;
+
+/**
+ * @author Ming
+ * 1/13/21
+ */
+public final class ThreadConfigs {
+
+ /**
+ * 线程的名称
+ */
+ public String name;
+ /**
+ * 线程执行延迟的时间
+ */
+ public long delay;
+
+ /**
+ * 用户任务的状态回调callback
+ */
+ public ThreadCallback callback;
+
+ /**
+ * 异步callback回调callback
+ */
+ public AsyncCallback asyncCallback;
+
+}
diff --git a/libs/src/main/java/com/libs/threadpool/ThreadManager.java b/libs/src/main/java/com/libs/threadpool/ThreadManager.java
new file mode 100644
index 0000000..d8d1246
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/ThreadManager.java
@@ -0,0 +1,156 @@
+package com.libs.threadpool;
+
+
+import androidx.annotation.NonNull;
+
+import com.libs.fragment.BaseApplication;
+import com.libs.threadpool.callback.AsyncCallback;
+import com.libs.threadpool.callback.OnTaskStart;
+import com.libs.utils.LogUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+
+/**
+ * 线程池管理类
+ *
+ * @author Ming
+ * 7/29/21
+ */
+public class ThreadManager {
+ private Map> futureMap = new HashMap<>();
+
+ /**
+ * 添加Future
+ *
+ * @param object
+ * @param taskBeans
+ */
+ public void add(Object object, TaskBean... taskBeans) {
+ if (futureMap.containsKey(object.hashCode())) {
+ List taskBeanList = futureMap.get(object.hashCode());
+ for (TaskBean taskBean : taskBeans) {
+ taskBeanList.add(taskBean);
+ }
+ } else {
+ List taskBeanList = new ArrayList<>();
+ for (TaskBean taskBean : taskBeans) {
+ taskBeanList.add(taskBean);
+ }
+ futureMap.put(object.hashCode(), taskBeanList);
+ }
+ }
+
+ /**
+ * 移除Future
+ *
+ * @param object
+ * @param taskBeans
+ */
+ public void remove(Object object, TaskBean... taskBeans) {
+ if (futureMap.containsKey(object.hashCode())) {
+ List taskBeanList = futureMap.get(object.hashCode());
+ for (TaskBean taskBean : taskBeans) {
+ taskBean.stopTask();
+ taskBeanList.remove(taskBean);
+ }
+ }
+ }
+
+ /**
+ * 移除批量Future
+ *
+ * @param object
+ */
+ public void remove(Object object) {
+ if (futureMap.containsKey(object.hashCode())) {
+ for (TaskBean taskBean : futureMap.get(object.hashCode())) {
+ taskBean.stopTask();
+ }
+ futureMap.remove(object.hashCode());
+ }
+ }
+
+ /**
+ * 非延迟任务
+ *
+ * @param runnable
+ */
+ public TaskBean execute(Object obj, Runnable runnable) {
+ TaskBean taskBean = new TaskBean();
+ Future mainFuture = BaseApplication.getInstance().getExecutor().execute(runnable, null);
+ taskBean.addFuture(mainFuture);
+ add(obj.hashCode(), taskBean);
+ return taskBean;
+ }
+
+ /**
+ * 延迟任务
+ *
+ * @param delay
+ * @param runnable
+ */
+ public TaskBean execute(Object obj, int delay, Runnable runnable) {
+ TaskBean taskBean = new TaskBean();
+ Future mainFuture = BaseApplication.getInstance().getExecutor().setDelay(delay).execute(runnable, new OnTaskStart() {
+ @Override
+ public void onStart(Future future) {
+ LogUtil.e("耗时操作");
+ taskBean.addFuture(future);
+ }
+ });
+ taskBean.addFuture(mainFuture);
+ add(obj.hashCode(), taskBean);
+ return taskBean;
+ }
+
+ /**
+ * 非延迟任务
+ *
+ * @param callable
+ * @param callback
+ * @param
+ */
+ public TaskBean execute(Object obj, @NonNull Callable callable, AsyncCallback callback) {
+ TaskBean taskBean = new TaskBean();
+ Future mainFuture = BaseApplication.getInstance().getExecutor().execute(callable, callback, null);
+ mainFuture.cancel(true);
+ taskBean.addFuture(mainFuture);
+ add(obj.hashCode(), taskBean);
+ return taskBean;
+ }
+
+ /**
+ * 延迟任务
+ *
+ * @param delay
+ * @param callable
+ * @param callback
+ * @param
+ */
+ public TaskBean execute(Object obj, int delay, @NonNull Callable callable, AsyncCallback callback) {
+ TaskBean taskBean = new TaskBean();
+ Future mainFuture = BaseApplication.getInstance().getExecutor().setDelay(delay).execute(callable, callback, new OnTaskStart() {
+ @Override
+ public void onStart(Future future) {
+ LogUtil.e("耗时操作");
+ taskBean.addFuture(future);
+ }
+ });
+ taskBean.addFuture(mainFuture);
+ add(obj.hashCode(), taskBean);
+ return taskBean;
+ }
+
+ public static ThreadManager getInstance() {
+ return ThreadManagerHolder.mInstance;
+ }
+
+ private static class ThreadManagerHolder {
+ private final static ThreadManager mInstance = new ThreadManager();
+ }
+}
diff --git a/libs/src/main/java/com/libs/threadpool/ThreadPoolInternal.java b/libs/src/main/java/com/libs/threadpool/ThreadPoolInternal.java
new file mode 100644
index 0000000..77372a6
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/ThreadPoolInternal.java
@@ -0,0 +1,56 @@
+package com.libs.threadpool;
+
+import com.libs.threadpool.callback.OnTaskStart;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Ming
+ * 1/13/21
+ */
+public class ThreadPoolInternal {
+ private ScheduledExecutorService dispatcher;
+ private volatile Future future;
+
+ private ThreadPoolInternal() {
+ dispatcher = Executors.newScheduledThreadPool(1, new ThreadFactory() {
+ @Override
+ public Thread newThread(Runnable runnable) {
+ Thread thread = new Thread(runnable);
+ thread.setName("Delay-Thread");
+ thread.setPriority(Thread.MAX_PRIORITY);
+ return thread;
+ }
+ });
+ }
+
+ public static ThreadPoolInternal getInstance() {
+ return ThreadPoolInternalHolder.mInstance;
+ }
+
+ public Future post(final ExecutorService pool, final RunnableWrapper task) {
+ return pool.submit(task);
+ }
+
+ public Future postDelay(long delay, final ExecutorService pool, final RunnableWrapper task, OnTaskStart onTaskStart) {
+ if (delay == 0) {
+ return post(pool, task);
+ }
+ Future delayFuture = dispatcher.schedule(() -> {
+ future = pool.submit(task);
+ onTaskStart.onStart(future);
+// task.setOnStartListener(future);
+ }, delay, TimeUnit.MILLISECONDS);
+ return delayFuture;
+ }
+
+
+ private static class ThreadPoolInternalHolder {
+ private final static ThreadPoolInternal mInstance = new ThreadPoolInternal();
+ }
+}
diff --git a/libs/src/main/java/com/libs/threadpool/TranRunnable.java b/libs/src/main/java/com/libs/threadpool/TranRunnable.java
new file mode 100644
index 0000000..93d3843
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/TranRunnable.java
@@ -0,0 +1,35 @@
+package com.libs.threadpool;
+
+import android.os.Handler;
+import android.os.Looper;
+
+import java.util.concurrent.Executor;
+
+/**
+ * @author Ming
+ * 1/13/21
+ */
+public class TranRunnable implements Executor {
+ private Handler main = new Handler(Looper.getMainLooper());
+
+ public static TranRunnable getInstance() {
+ return TranRunnableHolder.mInstance;
+ }
+
+ @Override
+ public void execute(Runnable runnable) {
+ if (Looper.myLooper() == Looper.getMainLooper() && runnable != null) {
+ runnable.run();
+ return;
+ }
+ main.post(() -> {
+ if (runnable != null) {
+ runnable.run();
+ }
+ });
+ }
+
+ private static class TranRunnableHolder {
+ private final static TranRunnable mInstance = new TranRunnable();
+ }
+}
diff --git a/libs/src/main/java/com/libs/threadpool/Type.java b/libs/src/main/java/com/libs/threadpool/Type.java
new file mode 100644
index 0000000..931b704
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/Type.java
@@ -0,0 +1,31 @@
+package com.libs.threadpool;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @author ming
+ * 1/13/21
+ */
+@Retention(RetentionPolicy.SOURCE)
+@IntDef({Type.FIXED, Type.CACHE, Type.SCHEDULED, Type.SINGLE})
+public @interface Type {
+ /**
+ * 线程数量固定的线程池,全部为核心线程,响应较快,不用担心线程会被回收。
+ */
+ int FIXED = 0;
+ /**
+ * 它是一个数量无限多的线程池,都是非核心线程,适合执行大量耗时小的任务
+ */
+ int CACHE = 1;
+ /**
+ * 有数量固定的核心线程,且有数量无限多的非核心线程,适合用于执行定时任务和固定周期的重复任务
+ */
+ int SCHEDULED = 2;
+ /**
+ * 有数量固定的核心线程,且有数量无限多的非核心线程,适合用于执行定时任务和固定周期的重复任务
+ */
+ int SINGLE = 3;
+}
diff --git a/libs/src/main/java/com/libs/threadpool/callback/AsyncCallback.java b/libs/src/main/java/com/libs/threadpool/callback/AsyncCallback.java
new file mode 100644
index 0000000..72ba018
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/callback/AsyncCallback.java
@@ -0,0 +1,32 @@
+package com.libs.threadpool.callback;
+
+
+/**
+ * @author Ming
+ * 1/13/21
+ */
+public interface AsyncCallback {
+
+ /**
+ * 开始执行回调
+ *
+ * @param threadName
+ */
+ void onStart(String threadName);
+
+ /**
+ * 成功时调用
+ *
+ * @param t
+ */
+ void onSuccess(T t);
+
+ /**
+ * 异常时调用
+ *
+ * @param t 异常
+ */
+ void onFailed(Throwable t);
+
+
+}
diff --git a/libs/src/main/java/com/libs/threadpool/callback/DefLogCallBack.java b/libs/src/main/java/com/libs/threadpool/callback/DefLogCallBack.java
new file mode 100644
index 0000000..3bc9dc0
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/callback/DefLogCallBack.java
@@ -0,0 +1,26 @@
+package com.libs.threadpool.callback;
+
+import android.util.Log;
+
+/**
+ * @author Ming
+ * 1/13/21
+ */
+public class DefLogCallBack implements ThreadCallback {
+ private final String TAG = "DefLogCallBack";
+
+ @Override
+ public void onError(String name, Throwable t) {
+ Log.i(TAG, "------onError" + "-----" + name + "----" + Thread.currentThread() + "----" + t.getMessage());
+ }
+
+ @Override
+ public void onCompleted(String name) {
+ Log.i(TAG, "------onCompleted" + "-----" + name + "----" + Thread.currentThread());
+ }
+
+ @Override
+ public void onStart(String threadName) {
+ Log.i(TAG, "------onStart" + "-----" + threadName + "----" + Thread.currentThread());
+ }
+}
diff --git a/libs/src/main/java/com/libs/threadpool/callback/MergeCallback.java b/libs/src/main/java/com/libs/threadpool/callback/MergeCallback.java
new file mode 100644
index 0000000..d36c028
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/callback/MergeCallback.java
@@ -0,0 +1,98 @@
+package com.libs.threadpool.callback;
+
+
+import java.util.concurrent.Executor;
+
+/**
+ * @author Ming
+ * 1/13/21
+ */
+public final class MergeCallback implements ThreadCallback, AsyncCallback {
+
+
+ private ThreadCallback callback;
+ private AsyncCallback async;
+ private Executor deliver;
+
+ public MergeCallback(ThreadCallback callback, Executor deliver, AsyncCallback async) {
+ this.callback = callback;
+ this.deliver = deliver;
+ this.async = async;
+ }
+
+ /**
+ * 回调成功
+ *
+ * @param o
+ */
+ @Override
+ public void onSuccess(final Object o) {
+ if (async == null) {
+ return;
+ }
+ deliver.execute(() -> {
+ try {
+ async.onSuccess(o);
+ } catch (Throwable t) {
+ onFailed(t);
+ }
+ });
+ }
+
+ /**
+ * 回调失败
+ *
+ * @param t 异常
+ */
+ @Override
+ public void onFailed(final Throwable t) {
+ if (async == null) {
+ return;
+ }
+ deliver.execute(() -> async.onFailed(t));
+ }
+
+ /**
+ * 回调异常
+ *
+ * @param name 线程name
+ * @param t 异常
+ */
+ @Override
+ public void onError(final String name, final Throwable t) {
+ onFailed(t);
+ if (callback == null) {
+ return;
+ }
+ deliver.execute(() -> callback.onError(name, t));
+ }
+
+ /**
+ * 回调完成
+ *
+ * @param name 线程name
+ */
+ @Override
+ public void onCompleted(final String name) {
+ if (callback == null) {
+ return;
+ }
+ deliver.execute(() -> callback.onCompleted(name));
+ }
+
+ /**
+ * 回调开始
+ *
+ * @param threadName 线程name
+ */
+ @Override
+ public void onStart(final String threadName) {
+ if (async != null) {
+ async.onStart(threadName);
+ }
+ if (callback == null) {
+ return;
+ }
+ deliver.execute(() -> callback.onStart(threadName));
+ }
+}
diff --git a/libs/src/main/java/com/libs/threadpool/callback/OnTaskStart.java b/libs/src/main/java/com/libs/threadpool/callback/OnTaskStart.java
new file mode 100644
index 0000000..a9b8352
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/callback/OnTaskStart.java
@@ -0,0 +1,11 @@
+package com.libs.threadpool.callback;
+
+import java.util.concurrent.Future;
+
+/**
+ * @author Ming
+ * 7/29/21
+ */
+public interface OnTaskStart {
+ void onStart(Future future);
+}
diff --git a/libs/src/main/java/com/libs/threadpool/callback/ThreadCallback.java b/libs/src/main/java/com/libs/threadpool/callback/ThreadCallback.java
new file mode 100644
index 0000000..5b0f23d
--- /dev/null
+++ b/libs/src/main/java/com/libs/threadpool/callback/ThreadCallback.java
@@ -0,0 +1,30 @@
+package com.libs.threadpool.callback;
+
+/**
+ * @author Ming
+ * 1/13/21
+ */
+public interface ThreadCallback {
+
+ /**
+ * 当线程发生错误时,将调用此方法。
+ *
+ * @param threadName 正在运行线程的名字
+ * @param t 异常
+ */
+ void onError(String threadName, Throwable t);
+
+ /**
+ * 通知用户知道它已经完成
+ *
+ * @param threadName 正在运行线程的名字
+ */
+ void onCompleted(String threadName);
+
+ /**
+ * 通知用户任务开始运行
+ */
+ void onStart(String threadName);
+
+
+}
diff --git a/libs/src/main/java/com/libs/utils/ActivityManager.java b/libs/src/main/java/com/libs/utils/ActivityManager.java
new file mode 100644
index 0000000..aa18dd5
--- /dev/null
+++ b/libs/src/main/java/com/libs/utils/ActivityManager.java
@@ -0,0 +1,172 @@
+package com.libs.utils;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.util.Log;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+
+public class ActivityManager {
+ private static Stack activityStack;
+ private static ActivityManager instance;
+ /**
+ * 行为轨迹
+ */
+ private static List behaviorTrackList;
+
+ private ActivityManager() {
+ }
+
+ public static ActivityManager getInstance() {
+ if (instance == null) {
+ instance = new ActivityManager();
+ }
+ return instance;
+ }
+
+ /**
+ * 将指定activity压入栈中
+ *
+ * @param activity
+ */
+ public void pushActivity(Activity activity) {
+ if (activityStack == null) {
+ activityStack = new Stack<>();
+ }
+ // 防止重复入栈
+ if (!activityStack.contains(activity)) {
+ activityStack.add(activity);
+ }
+ }
+
+ /**
+ * 销毁最顶层的activity
+ */
+ public void popActivity() {
+ Activity activity = activityStack.lastElement();
+ popActivity(activity);
+ }
+
+ /**
+ * 销毁指定activity
+ *
+ * @param activity
+ */
+ public void popActivity(Activity activity) {
+ if (activity != null) {
+ activityStack.remove(activity);
+ if (!activity.isFinishing()) {
+ activity.finish();
+ }
+ activity = null;
+ }
+ }
+
+ /**
+ * 返回最顶层activity实例
+ *
+ * @return
+ */
+ public Activity currentActivity() {
+ Activity activity = null;
+ if (activityStack != null && !activityStack.isEmpty()) {
+ activity = activityStack.lastElement();
+ }
+ return activity;
+ }
+
+ /**
+ * 判断栈中是否有某个Activity
+ *
+ * @param cls
+ * @return
+ */
+ public boolean hasActivity(Class cls) {
+ for (Activity act : activityStack) {
+ if (act.getComponentName().getClassName().equals(cls.getName())) {
+ Log.i("ScreenManager", cls.getName() + " is found.");
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 返回栈中某个Activity
+ *
+ * @param cls
+ * @return
+ */
+ private Activity getActivity(Class cls) {
+ for (Activity act : activityStack) {
+ if (act.getComponentName().getClassName().equals(cls.getName())) {
+ Log.i("ScreenManager", cls.getName() + " is found.");
+ return act;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 除了指定activity其余的全部销毁
+ *
+ * @param cls
+ */
+ public void popAllActivityExceptOne(Class cls) {
+ while (true) {
+ Activity activity = currentActivity();
+ if (activity == null) {
+ break;
+ }
+ if (cls != null && activity.getClass().getName().equals(cls.getName())) {
+ break;
+ }
+ popActivity(activity);
+ }
+ }
+
+ public void popActivities(Class... clss) {
+ int len = clss.length;
+ for (Class cls : clss) {
+ Activity activity = getActivity(cls);
+ if (activity != null) {
+ popActivity(activity);
+ }
+ }
+ }
+
+ public static void startActivity(Activity activity, Class> cls) {
+ activity.startActivity(new Intent(activity, cls));
+ }
+
+ public Activity isAppShow() {
+ Stack activityStacks = activityStack;
+ if (!DataUtil.isNull(activityStacks)) {
+ for (Activity activity : activityStacks) {
+ try {
+ Method isResumed = activity.getClass().getMethod("isResumed");
+ boolean resumed = (boolean) isResumed.invoke(activity, new Object[]{});
+ if (resumed == true) {
+ return activity;
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public void behaviorTrack(Activity activity) {
+ if (behaviorTrackList == null) {
+ behaviorTrackList = new ArrayList<>();
+ }
+ behaviorTrackList.add(activity);
+ }
+
+}
diff --git a/libs/src/main/java/com/libs/utils/DataUtil.java b/libs/src/main/java/com/libs/utils/DataUtil.java
new file mode 100644
index 0000000..317114f
--- /dev/null
+++ b/libs/src/main/java/com/libs/utils/DataUtil.java
@@ -0,0 +1,85 @@
+package com.libs.utils;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+/**
+ * @author Ming
+ * 7/21/21
+ */
+public class DataUtil {
+
+ public static boolean isNull(Object object) {
+ if (object == null) {
+ return true;
+ }
+ if (object instanceof List) {
+ if (((List) object).size() == 0) {
+ return true;
+ }
+ } else if (object instanceof Stack) {
+ if (((Stack) object).size() == 0) {
+ return true;
+ }
+ } else if (object instanceof Map) {
+ if (((Map) object).size() == 0) {
+ return true;
+ }
+ } else if (object instanceof Set) {
+ if (((Set) object).size() == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static int getLength(Object obj) {
+ if (obj == null) {
+ return 0;
+ }
+ if (obj instanceof List) {
+ return ((List) obj).size();
+ }
+ return 0;
+ }
+
+
+ public static Object getData(Object obj, int position) {
+ if (obj == null) {
+ return null;
+ }
+ if (obj instanceof List) {
+ return ((List) obj).get(position);
+ }
+ return null;
+ }
+
+
+ public static Object mergeList(List... lists) {
+ if (lists == null) {
+ return null;
+ }
+ if (lists.length == 0) {
+ return null;
+ }
+ List