1、build.gradle添加依赖
//jetpack组件库
api 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
api 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
api "com.google.code.gson:gson:2.8.5"
//retrofit网络请求 、 okhttp网络请求和Rxjava3
api "com.squareup.okhttp3:logging-interceptor:4.7.2"
api "com.squareup.retrofit2:converter-gson:2.9.0"
api "com.squareup.retrofit2:retrofit:2.9.0"
api "com.squareup.retrofit2:adapter-rxjava3:2.9.0"
//glide图片加载
api 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
//RxAndroid RxLifecycle是为了防止RxJava中subscription导致内存泄漏而诞生的,核心思想是通过监听Activity、Fragment的生命周期,来自动断开subscription以防止内存泄漏
api 'com.trello.rxlifecycle4:rxlifecycle:4.0.2'
api 'com.trello.rxlifecycle4:rxlifecycle-components:4.0.2'
api 'com.trello.rxlifecycle4:rxlifecycle-android:4.0.2'
api 'com.alibaba:arouter-api:1.5.1'
2、新建BaseActivity、BaseFragment? ?以防止内存泄漏? 继承RxAppCompatActivity和RxFragment
public class BaseActivity extends RxAppCompatActivity {
}
public class BaseFragment extends RxFragment {
}
3、Application增加registerActivityLifecycleCallbacks? 可以监听到?Activity 的状态,从而可以判断 APP 是否在前台或者后台等
public class EnterApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
AppGlobalVar.appContext = base;
AppGlobalVar.currentLanguage = LanguageHandler.getInstance().getLanguage();
super.attachBaseContext(LanguageHandler.getInstance().setLocal(base));
}
@Override
public void onCreate() {
super.onCreate();
CrashHandler.getInstance().init(this);
//路由初始化
if (AppGlobalVar.isDebug) {
ARouter.openLog();
ARouter.openDebug();
}
ARouter.init(this);
int myPid = android.os.Process.myPid();
DataStoreManager.init(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
String processName = AppUtils.getProcessName(this, myPid);
if (!BuildConfig.APPLICATION_ID.equals(processName)) {
String processEndSuffix = StringUtils.getProcessEndfix(processName);
if (TextUtils.isEmpty(processEndSuffix)) {
processEndSuffix = "other";
}
WebView.setDataDirectorySuffix(processEndSuffix);
}
}
registerActivityLifecycleCallbacks(new AppActivityLifecycleCallbacks());
}
}
public class AppActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
ActivityStackManager.add(activity);
}
@Override
public void onActivityStarted(@NonNull Activity activity) {
}
@Override
public void onActivityResumed(@NonNull Activity activity) {
isAppBackground = false;//app回到前台
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
}
@Override
public void onActivityStopped(@NonNull Activity activity) {
isAppBackground = true;//app在后台
}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
ActivityStackManager.remove(activity);
}
}
4、网络请求类? 采用Retrofit网络请求
public class NetworkManager {
private static String DEFAULT_BASE_URL = "http://api.xx.retrofit.com/";
private CommonInterceptor commonInterceptor;
private static final Map<String, Retrofit> retrofitMap = new HashMap<>();
private CookieJar cookieJar;
private static NetworkManager instance;
private NetworkManager() {
}
public static NetworkManager getInstance() {
if (instance == null) {
instance = new NetworkManager();
}
return instance;
}
public void setDefaultDomain(String domain) {
if (!TextUtils.isEmpty(domain)) {
if (!domain.endsWith("/")) {
domain += "/";
}
DEFAULT_BASE_URL = domain;
}
}
public String getDefaultDomain() {
return DEFAULT_BASE_URL;
}
public void setCommonParams(Map<String, String> commonParams) {
commonInterceptor = new CommonInterceptor(commonParams);
}
public void setCookieJar(CookieJar cookieJar) {
this.cookieJar = cookieJar;
}
private Retrofit buildRetrofit() {
return buildRetrofit(DEFAULT_BASE_URL);
}
private Retrofit buildRetrofit(String baseUrl) {
Retrofit retrofit;
if (retrofitMap.containsKey(baseUrl)) {
retrofit = retrofitMap.get(baseUrl);
} else {
OkHttpClient.Builder builder = new OkHttpClient.Builder();
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
builder.addInterceptor(loggingInterceptor);
if (commonInterceptor != null) {
builder.addInterceptor(commonInterceptor);
}
if (cookieJar != null) {
builder.cookieJar(cookieJar);
}
OkHttpClient okHttpClient = builder
.readTimeout(10, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
.retryOnConnectionFailure(true)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(CustomGsonConverterFactory.create())
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
.build();
retrofitMap.put(baseUrl, retrofit);
}
return retrofit;
}
public <T> T create(final Class<T> service) {
return buildRetrofit().create(service);
}
public <T> T create(String baseUrl, final Class<T> service) {
return buildRetrofit(baseUrl).create(service);
}
}
5、网络请求interface?
public interface ListService {
@GET("/Product/List")
Observable<BaseResponse<ListCard>> getActList(@QueryMap Map<String, String> paramsMap);
}
//@GET("/Product/List") 接口名
//ListCard实体类 可以通过RoboPOJOGenerator插件生成
//@QueryMap Map<String, String> paramsMap 是传入map参数
//如果传入string参数 可以这样写@Query("item_id") String item_id,@Query("page") int page
public class ListCard {
@SerializedName("image")
public String image;
@SerializedName("currPage")
public Integer currPage;
@SerializedName("pageTotal")
public Integer pageTotal;
@SerializedName("prePage")
public Integer prePage;
@SerializedName("list")
public List<ProductCard> list;
@SerializedName("title")
public String title;
@SerializedName("desc")
public String desc;
}
6、创建ViewModel+LiveData
public class ListViewModel extends ViewModel {
private ListService listService;
private final SingleLiveData<ListCard> listData = new SingleLiveData<>();
public MutableLiveData<Integer> listError = new MutableLiveData<>();
public MutableLiveData<ListCard> getActListData(Context context, Map<String, String> paramsMap){
if (listService == null) {
listService = NetworkManager.getInstance().create(ListService.class);
}
listService.getActList(paramsMap)
.compose(RxJavaHelper.observableIO2Main(context))
.subscribe(new BaseObserver<ListCard>() {
@Override
public void onSuccess(ListCard result) {
listData.postValue(result);
}
@Override
public void onFailure(NetworkException e) {
listError.postValue(-1);
}
});
return listData;
}
}
//因为数据需要分页加载 用SingleLiveData
public class SingleLiveData<T> extends MutableLiveData<T> {
private final AtomicBoolean atomicBoolean = new AtomicBoolean(false);
@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer<? super T> observer) {
super.observe(owner, t -> {
if (atomicBoolean.compareAndSet(true, false)) {
observer.onChanged(t);
}
});
}
@Override
public void postValue(T value) {
atomicBoolean.set(true);
super.postValue(value);
}
}
public class RxJavaHelper {
public static <T> ObservableTransformer<T, T> observableIO2Main(final Context context) {
return upstream -> {
Observable<T> observable = upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
return composeContext(context, observable);
};
}
public static <T> ObservableTransformer<T, T> observableIO2Main(final RxFragment fragment) {
return upstream -> upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()).compose(fragment.<T>bindToLifecycle());
}
public static <T> FlowableTransformer<T, T> flowableIO2Main() {
return upstream -> upstream
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
private static <T> ObservableSource<T> composeContext(Context context, Observable<T> observable) {
if (context instanceof RxActivity) {
return observable.compose(((RxActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
} else if (context instanceof RxFragmentActivity) {
return observable.compose(((RxFragmentActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
} else if (context instanceof RxAppCompatActivity) {
return observable.compose(((RxAppCompatActivity) context).bindUntilEvent(ActivityEvent.DESTROY));
} else {
return observable;
}
}
}
/**
用于这种网络结构
{
"code": "40000",
"action": "",
"message": "hhhh",
"data": {}
}
*/
public class BaseResponse<T> {
public int code;
public String message;
public String action;
public T data;
}
public abstract class BaseObserver<T> implements Observer<BaseResponse<T>> {
private final String TAG = "BaseObserver";
public static final String ACTION_TOAST = "toast";
@Override
public void onSubscribe(@NonNull Disposable d) {
LogUtils.i(TAG, "onSubscribe");
}
@Override
public void onNext(@NonNull BaseResponse<T> baseResponse) {
LogUtils.i(TAG, "onNext: message = %s ; code = %d", baseResponse.message, baseResponse.code);
if (baseResponse.code == 0) {
if (baseResponse.data == null) {
LogUtils.e(TAG, "onNext: data is null");
onFailure(new NetworkException(baseResponse.action, "data is null", NetworkException.CODE_DATA_NULL));
} else {
onSuccess(baseResponse.data);
}
} else {
onFailure(new NetworkException(baseResponse.action, baseResponse.message, baseResponse.code));
}
onAction(baseResponse.action, baseResponse.message);
}
@Override
public void onError(@NonNull Throwable e) {
String errorMsg = NetworkError.handler(e);
LogUtils.e(TAG, "onError: %s ; code = %d", errorMsg, NetworkException.CODE_ERROR);
onFailure(new NetworkException("", errorMsg, -1));
}
@Override
public void onComplete() {
LogUtils.i(TAG, "onComplete");
}
public abstract void onSuccess(T result);
public abstract void onFailure(NetworkException e);
public boolean isToast(String action) {
return TextUtils.equals(action, ACTION_TOAST);
}
protected void onAction(String action, String message) {
if (isShowToast()) {
showToast(action, message);
}
}
/**
* 是否显示toast ,默认不弹
*/
protected boolean isShowToast() {
return false;
}
private void showToast(String action, String message) {
if (isToast(action)) {
ToastUtils.showCenterToast(message);
}
}
}
public class NetworkException extends Exception {
public static final int CODE_DATA_NULL = 80000; // 空数据
public static final int CODE_ERROR = -99999;// 异常
private String action;
private String message;
private final int errorCode;
public int getErrorCode() {
return errorCode;
}
public String getAction() {
return action;
}
public String getMessage() {
return message;
}
public NetworkException(String action, String message, int errorCode) {
super(message);
this.action = action;
this.errorCode = errorCode;
this.message = message;
}
}
7、Activity请求接口
@Route(path = RoutePath.APP_ACT_LIST)
public class ListActivity extends BaseActivity {
private String LOG_TAG = "ListActivity";
private ActivityActListBinding binding;
private int currPage = 1;
private ListViewModel listViewModel;
private ActListAdapter actListAdapter;
private Map<String, String> paramsMap;
@Override
public View getBindingView() {
binding = ActivityActListBinding.inflate(getLayoutInflater());
return binding.getRoot();
}
@Override
public void initPage() {
StatusBarUtil.immersiveTitleView(binding.actHeadLayout);
binding.rvActList.setLayoutManager(new LinearLayoutManager(this));
binding.rvActList.addItemDecoration(new ActSpacesItemDecoration(this));
paramsMap = getIntentParams();
actListAdapter = new ActListAdapter(this);
binding.rvActList.setAdapter(actListAdapter);
actListViewModel = new ViewModelProvider(this).get(ListViewModel.class);
requestActList(1);
actListViewModel.actListError.observe(this, integer -> {
//update ui
LogUtils.e(LOG_TAG, "请求出错");
});
binding.actBack.setOnClickListener(view -> finish());
binding.rvActList.setLoadMoreListener(() -> {
currPage++;
requestActList(currPage);
});
}
private void requestActList(int page) {
paramsMap.put("page",page+"");
actListViewModel.getActListData(this,paramsMap).observe(this, actListCard -> {
//update ui
LogUtils.e(LOG_TAG, "请求成功");
if (actListCard != null) {
binding.bigActTitle.setText(actListCard.title);
binding.smallActTitle.setText(actListCard.desc);
boolean hasMore = false;
currPage = actListCard.currPage;
if (currPage == 1) {
actListAdapter.setData(actListCard.list);
Log.d(LOG_TAG, "setData" + currPage);
} else {
actListAdapter.addData(actListCard.list);
Log.d(LOG_TAG, "addData" + currPage);
}
hasMore = currPage < actListCard.pageTotal;
actListAdapter.setHasMore(hasMore);
binding.rvActList.notifyMoreFinish(hasMore);
}
});
}
}
|