update mvvm
This commit is contained in:
@@ -50,7 +50,7 @@ android {
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
viewBinding{
|
||||
viewBinding {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
@@ -142,14 +142,18 @@ dependencies {
|
||||
|
||||
//okhttp
|
||||
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
|
||||
//log打印
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
|
||||
//Retrofit
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'
|
||||
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
|
||||
// gson converter
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
|
||||
// 标准转换器,去掉 Retrofit以Mutipart上传参数时,String参数会多一对双引号
|
||||
implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
|
||||
|
||||
|
||||
//RxJava
|
||||
implementation 'io.reactivex.rxjava3:rxjava:3.0.0'
|
||||
implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
|
||||
@@ -189,6 +193,8 @@ dependencies {
|
||||
implementation 'com.gitee.zackratos:UltimateBarX:0.8.0'
|
||||
// //验证码输入
|
||||
// implementation 'com.jacktuotuo.customview:verificationcodeview:1.0.5'
|
||||
//动态权限框架
|
||||
// implementation 'com.hjq:xxpermissions:6.0'
|
||||
// 权限请求框架:https://github.com/getActivity/XXPermissions
|
||||
implementation 'com.github.getActivity:XXPermissions:18.63'
|
||||
// 吐司框架:https://github.com/getActivity/Toaster
|
||||
implementation 'com.github.getActivity:Toaster:12.6'
|
||||
}
|
||||
|
||||
@@ -6,15 +6,16 @@
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
<application
|
||||
android:name="com.ttstd.template.base.BaseApplication"
|
||||
android:name=".base.BaseApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:networkSecurityConfig="@xml/network"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name="com.ttstd.template.activity.main.MainActivity"
|
||||
android:name=".activity.main.MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
@@ -23,6 +24,13 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activity.template.mvp.TemplateActivity"
|
||||
android:exported="true" />
|
||||
|
||||
<activity
|
||||
android:name=".activity.template.mvvm.MvvmActivity"
|
||||
android:exported="true" />
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
@@ -37,9 +45,9 @@
|
||||
<!-- 这个 Demo 主要展示副单位的用法, 如果只使用副单位 (pt、in、mm) 就可以直接以像素作为单位填写设计图的尺寸, 不需再把像素转化为 dp-->
|
||||
<meta-data
|
||||
android:name="design_width_in_dp"
|
||||
android:value="1080"/>
|
||||
android:value="1080" />
|
||||
<meta-data
|
||||
android:name="design_height_in_dp"
|
||||
android:value="1920"/>
|
||||
android:value="1920" />
|
||||
</application>
|
||||
</manifest>
|
||||
@@ -1,10 +1,22 @@
|
||||
package com.ttstd.template.activity.main;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.ttstd.template.R;
|
||||
import com.ttstd.template.activity.template.mvp.TemplateActivity;
|
||||
import com.ttstd.template.activity.template.mvvm.MvvmActivity;
|
||||
import com.ttstd.template.base.BaseActivity;
|
||||
|
||||
public class MainActivity extends BaseActivity {
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class MainActivity extends BaseActivity {
|
||||
@BindView(R.id.bt_mvp)
|
||||
Button bt_mvp;
|
||||
@BindView(R.id.bt_mvvm)
|
||||
Button bt_mvvm;
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
@@ -12,8 +24,30 @@ public class MainActivity extends BaseActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initView() {
|
||||
protected boolean setNightMode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setfitWindow() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initView() {
|
||||
ButterKnife.bind(this);
|
||||
bt_mvp.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startActivity(new Intent(MainActivity.this, TemplateActivity.class));
|
||||
}
|
||||
});
|
||||
bt_mvvm.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
startActivity(new Intent(MainActivity.this, MvvmActivity.class));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,30 +1,39 @@
|
||||
package com.ttstd.template.activity.template;
|
||||
package com.ttstd.template.activity.template.mvp;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.ttstd.template.R;
|
||||
import com.ttstd.template.base.BaseLightActivity;
|
||||
import com.ttstd.template.base.mvp.BaseMvpActivity;
|
||||
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class TemplateActivity extends BaseLightActivity implements TemplateContact.TemplateView {
|
||||
|
||||
public class TemplateActivity extends BaseMvpActivity implements TemplateContact.TemplateView {
|
||||
private static final String TAG = TemplateActivity.class.getSimpleName();
|
||||
|
||||
private TemplatePresenter mPresenter;
|
||||
|
||||
@Override
|
||||
public int getLayoutId() {
|
||||
return R.layout.activity_video;
|
||||
return R.layout.activity_main;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setNightMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setfitWindow() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initView() {
|
||||
ButterKnife.bind(this);
|
||||
mPresenter = new TemplatePresenter(this);
|
||||
mPresenter.setLifecycle(lifecycleSubject);
|
||||
mPresenter.setLifecycle(getLifecycleSubject());
|
||||
mPresenter.attachView(this);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.ttstd.template.activity.template;
|
||||
package com.ttstd.template.activity.template.mvp;
|
||||
|
||||
import com.ttstd.template.base.BasePresenter;
|
||||
import com.ttstd.template.base.BaseView;
|
||||
import com.ttstd.template.base.mvp.BasePresenter;
|
||||
import com.ttstd.template.base.mvp.BaseView;
|
||||
|
||||
public class TemplateContact {
|
||||
interface Presenter extends BasePresenter<TemplateView> {
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.ttstd.template.activity.template;
|
||||
package com.ttstd.template.activity.template.mvp;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.ttstd.template.activity.template.mvvm;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.lifecycle.Observer;
|
||||
|
||||
import com.ttstd.template.R;
|
||||
import com.ttstd.template.base.mvvm.BaseMvvmActivity;
|
||||
import com.ttstd.template.databinding.ActivityMvvmBinding;
|
||||
|
||||
public class MvvmActivity extends BaseMvvmActivity<MvvmViewModel, ActivityMvvmBinding> {
|
||||
private static final String TAG = MvvmActivity.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
protected int getLayoutId() {
|
||||
return R.layout.activity_mvvm;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setNightMode() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean setfitWindow() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initDataBinding() {
|
||||
mViewModel.setCtx(this);
|
||||
mViewModel.setVDBinding(mViewDataBinding);
|
||||
mViewModel.setLifecycle(getLifecycleSubject());
|
||||
|
||||
mViewModel.getData().observe(this, new Observer<String>() {
|
||||
@Override
|
||||
public void onChanged(String s) {
|
||||
Log.e(TAG, "onChanged: " + s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initView() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initData() {
|
||||
mViewModel.setData("mvvm");
|
||||
mViewModel.getIp();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.ttstd.template.activity.template.mvvm;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import com.ttstd.template.base.mvvm.BaseViewModel;
|
||||
import com.ttstd.template.databinding.ActivityMvvmBinding;
|
||||
import com.ttstd.template.network.NetInterfaceManager;
|
||||
|
||||
public class MvvmViewModel extends BaseViewModel<ActivityMvvmBinding> {
|
||||
private static final String TAG = MvvmViewModel.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityMvvmBinding getVDBinding() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
private MutableLiveData<String> mData = new MutableLiveData<>();
|
||||
|
||||
public MutableLiveData<String> getData() {
|
||||
return mData;
|
||||
}
|
||||
|
||||
public void setData(String s) {
|
||||
mData.setValue(s);
|
||||
mData.postValue(s);
|
||||
}
|
||||
|
||||
public void getIp() {
|
||||
NetInterfaceManager.getInstance().getPublicIp(getLifecycle(), new NetInterfaceManager.PublicIpCallbak() {
|
||||
@Override
|
||||
public void getPublicIp(String ip) {
|
||||
Log.e(TAG, "getPublicIp: " + ip);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,134 +1,32 @@
|
||||
package com.ttstd.template.base;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.CheckResult;
|
||||
import androidx.annotation.ContentView;
|
||||
import androidx.annotation.LayoutRes;
|
||||
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 com.ttstd.template.R;
|
||||
import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
|
||||
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject;
|
||||
|
||||
|
||||
public abstract class BaseActivity extends AppCompatActivity implements LifecycleProvider<ActivityEvent> {
|
||||
public final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
// StatusBarUtil.init(this);
|
||||
UltimateBarX.statusBar(this)
|
||||
.transparent()
|
||||
.colorRes(R.color.colorPrimaryDark)
|
||||
.light(true)
|
||||
.apply();
|
||||
UltimateBarX.navigationBar(this)
|
||||
.transparent()
|
||||
.colorRes(R.color.colorPrimaryDark)
|
||||
.light(true)
|
||||
.apply();
|
||||
setContentView(this.getLayoutId());
|
||||
initView();
|
||||
initData();
|
||||
//最近任务和应用图标不一样
|
||||
if (Build.VERSION.SDK_INT > 27) {
|
||||
ActivityManager.TaskDescription description = new ActivityManager.TaskDescription(getString(R.string.app_name), R.mipmap.ic_launcher, getColor(R.color.colorPrimary));
|
||||
this.setTaskDescription(description);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置布局
|
||||
*/
|
||||
public abstract int getLayoutId();
|
||||
|
||||
/**
|
||||
* 初始化视图
|
||||
*/
|
||||
public abstract void initView();
|
||||
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
public abstract void initData();
|
||||
public abstract class BaseActivity extends BaseTransparentActivity {
|
||||
|
||||
public BaseActivity() {
|
||||
super();
|
||||
}
|
||||
|
||||
@ContentView
|
||||
public BaseActivity(@LayoutRes int contentLayoutId) {
|
||||
super(contentLayoutId);
|
||||
}
|
||||
|
||||
@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 onStart() {
|
||||
super.onStart();
|
||||
lifecycleSubject.onNext(ActivityEvent.START);
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(getLayoutId());
|
||||
initView();
|
||||
initData();
|
||||
}
|
||||
|
||||
@Override
|
||||
@CallSuper
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
lifecycleSubject.onNext(ActivityEvent.RESUME);
|
||||
}
|
||||
/**
|
||||
* 初始化视图
|
||||
*/
|
||||
protected abstract void initView();
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
protected abstract void initData();
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.ttstd.template.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.ttstd.template.R;
|
||||
import com.ttstd.template.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();
|
||||
|
||||
/**
|
||||
* @return 是否是入侵
|
||||
*/
|
||||
protected abstract boolean setfitWindow();
|
||||
|
||||
|
||||
protected abstract void initDataBinding();
|
||||
|
||||
/**
|
||||
* 初始化视图
|
||||
*/
|
||||
protected abstract void initView();
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
protected abstract void initData();
|
||||
}
|
||||
@@ -1,72 +1,15 @@
|
||||
package com.ttstd.template.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.CheckResult;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import com.ttstd.template.base.rx.BaseRxFragment;
|
||||
|
||||
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;
|
||||
|
||||
public abstract class BaseFragment extends Fragment implements LifecycleProvider<FragmentEvent> {
|
||||
public final BehaviorSubject<FragmentEvent> lifecycleSubject = BehaviorSubject.create();
|
||||
public abstract class BaseFragment extends BaseRxFragment {
|
||||
|
||||
protected boolean isViewInitiated;
|
||||
protected boolean isVisibleToUser;
|
||||
protected boolean isDataInitiated;
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
return super.onCreateView(inflater, container, savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
@@ -92,65 +35,10 @@ public abstract class BaseFragment extends Fragment implements LifecycleProvider
|
||||
if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) {
|
||||
fetchData();
|
||||
//注释掉保证每次都更新数据
|
||||
isDataInitiated = true;
|
||||
// isDataInitiated = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
|
||||
273
app/src/main/java/com/ttstd/template/base/BaseMvvmFragment.java
Normal file
273
app/src/main/java/com/ttstd/template/base/BaseMvvmFragment.java
Normal file
@@ -0,0 +1,273 @@
|
||||
package com.ttstd.template.base;
|
||||
|
||||
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 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 mTag = 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;
|
||||
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) {
|
||||
//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);
|
||||
|
||||
// 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();
|
||||
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 initDataBinding();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// 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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
56
app/src/main/java/com/ttstd/template/base/BaseService.java
Normal file
56
app/src/main/java/com/ttstd/template/base/BaseService.java
Normal file
@@ -0,0 +1,56 @@
|
||||
package com.ttstd.template.base;
|
||||
|
||||
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 BaseService extends Service implements LifecycleProvider<ActivityEvent> {
|
||||
public final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
|
||||
|
||||
public BaseService() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.ttstd.template.base;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.ttstd.template.R;
|
||||
import com.ttstd.template.base.rx.BaseRxActivity;
|
||||
import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
|
||||
|
||||
public abstract class BaseTransparentActivity extends BaseRxActivity {
|
||||
|
||||
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();
|
||||
|
||||
/**
|
||||
* @return 是否是入侵
|
||||
*/
|
||||
protected abstract boolean setfitWindow();
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.ttstd.template.base;
|
||||
|
||||
public interface BaseView {
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.ttstd.template.base.mvp;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.ttstd.template.base.BaseTransparentActivity;
|
||||
|
||||
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();
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.ttstd.template.base;
|
||||
package com.ttstd.template.base.mvp;
|
||||
|
||||
public interface BasePresenter<V extends BaseView> {
|
||||
void attachView(V view);
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.ttstd.template.base.mvp;
|
||||
|
||||
public interface BaseView {
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package com.ttstd.template.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.ttstd.template.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();
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package com.ttstd.template.base.mvvm;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.databinding.ViewDataBinding;
|
||||
import androidx.lifecycle.ViewModel;
|
||||
|
||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject;
|
||||
|
||||
/**
|
||||
* 所有viewmodel的基类
|
||||
*/
|
||||
public abstract class BaseViewModel<VDB extends ViewDataBinding> 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<ActivityEvent> mBehaviorSubject;
|
||||
|
||||
@Override
|
||||
public void setLifecycle(BehaviorSubject subject) {
|
||||
this.mBehaviorSubject =subject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BehaviorSubject<ActivityEvent> getLifecycle() {
|
||||
return mBehaviorSubject;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.ttstd.template.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();
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
package com.ttstd.template.base;
|
||||
package com.ttstd.template.base.rx;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.CheckResult;
|
||||
import androidx.annotation.ContentView;
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
@@ -15,23 +13,19 @@ import com.trello.rxlifecycle4.LifecycleTransformer;
|
||||
import com.trello.rxlifecycle4.RxLifecycle;
|
||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||
import com.trello.rxlifecycle4.android.RxLifecycleAndroid;
|
||||
import com.ttstd.template.R;
|
||||
import com.zackratos.ultimatebarx.ultimatebarx.java.UltimateBarX;
|
||||
|
||||
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 abstract class BaseLightActivity extends AppCompatActivity implements LifecycleProvider<ActivityEvent> {
|
||||
public final BehaviorSubject<ActivityEvent> lifecycleSubject = BehaviorSubject.create();
|
||||
|
||||
public BaseLightActivity() {
|
||||
super();
|
||||
}
|
||||
|
||||
@ContentView
|
||||
public BaseLightActivity(@LayoutRes int contentLayoutId) {
|
||||
super(contentLayoutId);
|
||||
public BehaviorSubject<ActivityEvent> getLifecycleSubject() {
|
||||
return lifecycleSubject;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,38 +54,8 @@ public abstract class BaseLightActivity extends AppCompatActivity implements Lif
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
lifecycleSubject.onNext(ActivityEvent.CREATE);
|
||||
// StatusBarUtil.init(this);
|
||||
UltimateBarX.statusBar(this)
|
||||
.transparent()
|
||||
.colorRes(R.color.colorPrimaryDark)
|
||||
.light(true)
|
||||
.apply();
|
||||
UltimateBarX.navigationBar(this)
|
||||
.transparent()
|
||||
.colorRes(R.color.colorPrimaryDark)
|
||||
.light(true)
|
||||
.apply();
|
||||
setContentView(this.getLayoutId());
|
||||
initView();
|
||||
initData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置布局
|
||||
*/
|
||||
public abstract int getLayoutId();
|
||||
|
||||
/**
|
||||
* 初始化视图
|
||||
*/
|
||||
public abstract void initView();
|
||||
|
||||
|
||||
/**
|
||||
* 初始化数据
|
||||
*/
|
||||
public abstract void initData();
|
||||
|
||||
@Override
|
||||
@CallSuper
|
||||
protected void onStart() {
|
||||
@@ -127,3 +91,4 @@ public abstract class BaseLightActivity extends AppCompatActivity implements Lif
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
|
||||
123
app/src/main/java/com/ttstd/template/base/rx/BaseRxFragment.java
Normal file
123
app/src/main/java/com/ttstd/template/base/rx/BaseRxFragment.java
Normal file
@@ -0,0 +1,123 @@
|
||||
package com.ttstd.template.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();
|
||||
}
|
||||
}
|
||||
|
||||
109
app/src/main/java/com/ttstd/template/bean/WhoisBean.java
Normal file
109
app/src/main/java/com/ttstd/template/bean/WhoisBean.java
Normal file
@@ -0,0 +1,109 @@
|
||||
package com.ttstd.template.bean;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class WhoisBean implements Serializable {
|
||||
private static final long serialVersionUID = -6537021620041268080L;
|
||||
|
||||
String ip;
|
||||
String pro;
|
||||
String proCode;
|
||||
String city;
|
||||
String cityCode;
|
||||
String region;
|
||||
String regionCode;
|
||||
String addr;
|
||||
String regionNames;
|
||||
String err;
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public String getPro() {
|
||||
return pro;
|
||||
}
|
||||
|
||||
public void setPro(String pro) {
|
||||
this.pro = pro;
|
||||
}
|
||||
|
||||
public String getProCode() {
|
||||
return proCode;
|
||||
}
|
||||
|
||||
public void setProCode(String proCode) {
|
||||
this.proCode = proCode;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public String getCityCode() {
|
||||
return cityCode;
|
||||
}
|
||||
|
||||
public void setCityCode(String cityCode) {
|
||||
this.cityCode = cityCode;
|
||||
}
|
||||
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
public void setRegion(String region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public String getRegionCode() {
|
||||
return regionCode;
|
||||
}
|
||||
|
||||
public void setRegionCode(String regionCode) {
|
||||
this.regionCode = regionCode;
|
||||
}
|
||||
|
||||
public String getAddr() {
|
||||
return addr;
|
||||
}
|
||||
|
||||
public void setAddr(String addr) {
|
||||
this.addr = addr;
|
||||
}
|
||||
|
||||
public String getRegionNames() {
|
||||
return regionNames;
|
||||
}
|
||||
|
||||
public void setRegionNames(String regionNames) {
|
||||
this.regionNames = regionNames;
|
||||
}
|
||||
|
||||
public String getErr() {
|
||||
return err;
|
||||
}
|
||||
|
||||
public void setErr(String err) {
|
||||
this.err = err;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return JsonParser.parseString(new Gson().toJson(this)).getAsJsonObject().toString();
|
||||
}
|
||||
}
|
||||
@@ -4,19 +4,33 @@ import android.annotation.SuppressLint;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.os.Environment;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tencent.mmkv.MMKV;
|
||||
import com.trello.rxlifecycle4.RxLifecycle;
|
||||
import com.trello.rxlifecycle4.android.ActivityEvent;
|
||||
import com.ttstd.template.bean.BaseResponse;
|
||||
import com.ttstd.template.bean.WhoisBean;
|
||||
import com.ttstd.template.comm.CommonConfig;
|
||||
import com.ttstd.template.network.api.GetWhoisApi;
|
||||
import com.ttstd.template.network.interceptor.RepeatRequestInterceptor;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.annotations.NonNull;
|
||||
import io.reactivex.rxjava3.core.Observer;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
import io.reactivex.rxjava3.subjects.BehaviorSubject;
|
||||
import okhttp3.Cache;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
@@ -57,7 +71,12 @@ public class NetInterfaceManager {
|
||||
builder.readTimeout(timeOut, TimeUnit.SECONDS);// 设置读取数据超时时间
|
||||
builder.retryOnConnectionFailure(true);// 设置进行连接失败重试
|
||||
builder.addInterceptor(new RepeatRequestInterceptor());
|
||||
|
||||
builder.addInterceptor(new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
|
||||
@Override
|
||||
public void log(@NotNull String s) {
|
||||
Log.e("HttpLoggingInterceptor", "log: " + s);
|
||||
}
|
||||
}).setLevel(HttpLoggingInterceptor.Level.BASIC));
|
||||
// 设置缓存文件路径
|
||||
String cacheDirectory = getCacheDir() + "/OkHttpCache";
|
||||
Cache cache = new Cache(new File(cacheDirectory), cacheSize);
|
||||
@@ -111,6 +130,9 @@ public class NetInterfaceManager {
|
||||
return okHttpClient;
|
||||
}
|
||||
|
||||
public static final String WHOIS_IP = "whois_ip_addr";
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* Observable
|
||||
@@ -155,4 +177,52 @@ public class NetInterfaceManager {
|
||||
void onComplete();
|
||||
}
|
||||
|
||||
public interface PublicIpCallbak {
|
||||
void getPublicIp(String ip);
|
||||
}
|
||||
|
||||
|
||||
public void getPublicIp(BehaviorSubject<ActivityEvent> lifecycle, PublicIpCallbak callbak) {
|
||||
Retrofit retrofit = new Retrofit.Builder()
|
||||
.client(NetInterfaceManager.getInstance().getOkHttpClient())
|
||||
.baseUrl(UrlAddress.PCONLINE_WHOIS)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava3CallAdapterFactory.create())
|
||||
.build();
|
||||
retrofit.create(GetWhoisApi.class)
|
||||
.getWhois(true)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.compose(RxLifecycle.bindUntilEvent(lifecycle, ActivityEvent.DESTROY))
|
||||
.subscribe(new Observer<WhoisBean>() {
|
||||
@Override
|
||||
public void onSubscribe(@NonNull Disposable d) {
|
||||
Log.e("getPublicIp", "onSubscribe: ");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(@NonNull WhoisBean whoisBean) {
|
||||
Log.e("getPublicIp", "onNext: " + whoisBean);
|
||||
if (whoisBean != null && !TextUtils.isEmpty(whoisBean.getIp())) {
|
||||
callbak.getPublicIp(whoisBean.getIp());
|
||||
MMKV.mmkvWithID(CommonConfig.MMKV_ID, MMKV.MULTI_PROCESS_MODE).encode(WHOIS_IP, whoisBean.getIp());
|
||||
} else {
|
||||
callbak.getPublicIp("unknown");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(@NonNull Throwable e) {
|
||||
Log.e("getPublicIp", "onError: ");
|
||||
callbak.getPublicIp("unknown");
|
||||
onComplete();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
Log.e("getPublicIp", "onComplete: ");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,77 +4,7 @@ public class UrlAddress {
|
||||
/*主页接口*/
|
||||
public static final String ROOT_URL = "https://led.zuoyepad.com/android/";
|
||||
|
||||
/*设备激活*/
|
||||
public static final String SN_ACTIVATION = "sn/snActivation";
|
||||
/*获取设备是否激活*/
|
||||
public static final String GET_SN_IS_ACTIVATION = "sn/getSnIsActivation";
|
||||
/*获取设备激活二维码链接*/
|
||||
public static final String ACTIVATION_QRCODE = "pay/getActivationQrcode";
|
||||
|
||||
/*获取文件*/
|
||||
public static final String GET_FILES = "file/getFiles";
|
||||
/*获取操作指南*/
|
||||
public static final String GET_OPERATION_GUIDE = "file/getFiles";
|
||||
|
||||
|
||||
/*上传屏幕截图*/
|
||||
public final static String UPLOAD_SCREEN_SNAPSHOT = "sn/uploadScreenshot";
|
||||
/*浏览器网址管控*/
|
||||
public final static String SET_BROWSER_URL = "control/getBrowser";
|
||||
/*浏览器书签管控*/
|
||||
public final static String SET_BROWSER_LABEL = "control/getLabel";
|
||||
/*上传控制面版截图*/
|
||||
public static final String UPLOAD_CONTROL_SCREENSHOT = "sn/uploadControlScreenshot";
|
||||
|
||||
|
||||
/*设备信息接口*/
|
||||
public static final String SNINFO = "sn/getSnInfo";
|
||||
/*获取用户头像和信息*/
|
||||
public static final String GET_USER_AVATAR_INFO = "sn/getUserAvatarInfo";
|
||||
/*获取设备类型*/
|
||||
public static final String GET_SN_TYPE = "sn/getSnType";
|
||||
/*获取正在运行的app*/
|
||||
public static final String RUN_NEW_APP = "app/runNewApp";
|
||||
/*获取所有应用*/
|
||||
public final static String GET_ALL_PACKAGE = "app/queryAllApp";
|
||||
/*绑定设备消息*/
|
||||
public final static String BIND_DEVICES = "sn/bindSn";
|
||||
/*获取系统设置*/
|
||||
public final static String GET_SETTINGS = "control/getSetting";
|
||||
/*获取强制下载*/
|
||||
public final static String GET_FORCE_INSTALL = "app/getForceDownload";
|
||||
/*发送卸载或者安装信息*/
|
||||
public final static String SEND_INSTALLEDORREMOVED = "app/addAppInstall";
|
||||
/*发送设备基本信息*/
|
||||
public final static String UPDATE_SNINFO = "sn/updateAdminSn";
|
||||
/*根据包名获取更新*/
|
||||
public final static String GET_NEWESTAPPUPDATE = "app/newestAppUpdate";
|
||||
/*获取禁用包名*/
|
||||
public static final String GET_APP_ICON = "getAppIcon";
|
||||
/*获取灰度更新*/
|
||||
public static final String GET_TEST_APP_INFO = "app/getTestAppInfo";
|
||||
/*获取wifi*/
|
||||
public static final String GET_WIFI_ALIAS_PW = "getWifi";
|
||||
|
||||
/*获取屏幕管控*/
|
||||
public final static String GET_SCREEN_LOCK = "sn/getScreenshot";
|
||||
/*获取锁屏密码*/
|
||||
public static final String LOCK_SCREEN_PWD = "sn/getLockScreenPwd";
|
||||
/*解除锁屏*/
|
||||
public static final String UPDATE_LOCK_SCREEN = "sn/updateLockScreen";
|
||||
|
||||
/*发送绑定验证码*/
|
||||
public static final String SEND_BIND_VER_CODE = "Sn/sendBindVerCode";
|
||||
/*手动绑定设备*/
|
||||
public static final String EQUIPMENT_BIND = "Sn/equipmentBind";
|
||||
|
||||
/*上传应用图标*/
|
||||
public static final String UPLOAD_APP_IMG = "collectData/uploadAppImg";
|
||||
/*获取应用库是否有图标*/
|
||||
public static final String GET_IS_APP_IMG = "collectData/getIsAppImg";
|
||||
|
||||
|
||||
/*通过ip获取信息*/
|
||||
public static final String PCONLINE_WHOIS = "http://whois.pconline.com.cn/";
|
||||
public static final String PCONLINE_WHOIS = "https://whois.pconline.com.cn/";
|
||||
public static final String WHOIS = "ipJson.jsp";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.ttstd.template.network.api;
|
||||
|
||||
import com.ttstd.template.bean.WhoisBean;
|
||||
import com.ttstd.template.network.UrlAddress;
|
||||
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
/**
|
||||
* @author : fanhuitong
|
||||
* e-mail :
|
||||
* @date : 2021/10/1814:39
|
||||
* desc :
|
||||
* version: 1.0
|
||||
*/
|
||||
public interface GetWhoisApi {
|
||||
@GET(UrlAddress.WHOIS)
|
||||
Observable<WhoisBean> getWhois(
|
||||
@Query("json") boolean json
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package com.ttstd.template.rv;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
public class EquallyDividedItemDecoration extends RecyclerView.ItemDecoration {
|
||||
private static final String TAG = EquallyDividedItemDecoration.class.getSimpleName();
|
||||
|
||||
private int mSpanCount;//横条目数量
|
||||
private int mHalfRowSpacing;//行间距的一半
|
||||
private int mHalfColumnSpacing;// 列间距的一半
|
||||
|
||||
|
||||
public EquallyDividedItemDecoration(int spanCount, int halfRowSpacing) {
|
||||
mSpanCount = spanCount;
|
||||
mHalfRowSpacing = halfRowSpacing;
|
||||
mHalfColumnSpacing = halfRowSpacing;
|
||||
}
|
||||
|
||||
public EquallyDividedItemDecoration(int spanCount, int halfRowSpacing, int halfColumnSpacing) {
|
||||
mSpanCount = spanCount;
|
||||
mHalfRowSpacing = halfRowSpacing;
|
||||
mHalfColumnSpacing = halfColumnSpacing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) {
|
||||
super.getItemOffsets(outRect, view, parent, state);
|
||||
int position = parent.getChildAdapterPosition(view); // 获取view 在adapter中的位置。
|
||||
Log.d(TAG, "getItemOffsets: position = " + position);
|
||||
|
||||
int itemCount = parent.getAdapter().getItemCount();//item全部数量
|
||||
Log.d(TAG, "getItemOffsets: itemCount = " + itemCount);
|
||||
|
||||
int column = position % mSpanCount; // view 所在的列
|
||||
Log.d(TAG, "getItemOffsets: column = " + column);
|
||||
|
||||
if (column == 0) {
|
||||
outRect.left = 2 * mHalfRowSpacing;
|
||||
outRect.right = mHalfRowSpacing;
|
||||
} else if (column == mSpanCount - 1) {
|
||||
outRect.left = mHalfRowSpacing;
|
||||
outRect.right = 2 * mHalfRowSpacing;
|
||||
} else {
|
||||
outRect.left = mHalfRowSpacing;
|
||||
outRect.right = mHalfRowSpacing;
|
||||
}
|
||||
|
||||
int row = (position / 3);//所在行
|
||||
Log.d(TAG, "getItemOffsets: row = " + row);
|
||||
int maxRow = (int) Math.ceil((double) itemCount / mSpanCount);//一共多少行
|
||||
Log.d(TAG, "getItemOffsets: maxRow = " + maxRow);
|
||||
|
||||
if (row == 0) {
|
||||
outRect.top = 2 * mHalfColumnSpacing;
|
||||
outRect.bottom = mHalfColumnSpacing;
|
||||
} else if (row == maxRow - 1) {
|
||||
outRect.top = mHalfColumnSpacing;
|
||||
outRect.bottom = 2 * mHalfColumnSpacing;
|
||||
} else {
|
||||
outRect.top = mHalfColumnSpacing;
|
||||
outRect.bottom = mHalfColumnSpacing;
|
||||
}
|
||||
|
||||
Log.d(TAG, "getItemOffsets: outRect.left = " + outRect.left);
|
||||
Log.d(TAG, "getItemOffsets: outRect.right = " + outRect.right);
|
||||
Log.d(TAG, "getItemOffsets: outRect.top = " + outRect.top);
|
||||
Log.d(TAG, "getItemOffsets: outRect.bottom = " + outRect.bottom);
|
||||
}
|
||||
}
|
||||
121
app/src/main/java/com/ttstd/template/utils/GlideLoadUtils.java
Normal file
121
app/src/main/java/com/ttstd/template/utils/GlideLoadUtils.java
Normal file
@@ -0,0 +1,121 @@
|
||||
package com.ttstd.template.utils;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.request.target.SimpleTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
|
||||
/**
|
||||
* Glide 加载 简单判空封装 防止异步加载数据时调用Glide 抛出异常
|
||||
* Created by Li_Xavier on 2017/6/20 0020.
|
||||
*/
|
||||
public class GlideLoadUtils {
|
||||
private String TAG = "ImageLoader";
|
||||
|
||||
/**
|
||||
* 借助内部类 实现线程安全的单例模式
|
||||
* 属于懒汉式单例,因为Java机制规定,内部类SingletonHolder只有在getInstance()
|
||||
* 方法第一次调用的时候才会被加载(实现了lazy),而且其加载过程是线程安全的。
|
||||
* 内部类加载的时候实例化一次instance。
|
||||
*/
|
||||
public GlideLoadUtils() {
|
||||
}
|
||||
|
||||
private static class GlideLoadUtilsHolder {
|
||||
private final static GlideLoadUtils INSTANCE = new GlideLoadUtils();
|
||||
}
|
||||
|
||||
public static GlideLoadUtils getInstance() {
|
||||
return GlideLoadUtilsHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Glide 加载 简单判空封装 防止异步加载数据时调用Glide 抛出异常
|
||||
*
|
||||
* @param context
|
||||
* @param url 加载图片的url地址 String
|
||||
* @param imageView 加载图片的ImageView 控件
|
||||
* @param default_image 图片展示错误的本地图片 id
|
||||
*/
|
||||
public void glideLoad(Context context, String url, ImageView imageView, int default_image) {
|
||||
if (context != null) {
|
||||
Glide.with(context).load(url).centerCrop().error(default_image).into(imageView);
|
||||
} else {
|
||||
Log.i(TAG, "Picture loading failed,context is null");
|
||||
}
|
||||
}
|
||||
|
||||
public void glideLoadc(Context context, String url, ImageView imageView, Drawable default_image) {
|
||||
if (context != null) {
|
||||
Glide.with(context).load(url).centerCrop().error(default_image).into(imageView);
|
||||
} else {
|
||||
Log.i(TAG, "Picture loading failed,context is null");
|
||||
}
|
||||
}
|
||||
|
||||
public void glideLoad(Activity activity, String url, ImageView imageView, Drawable drawable) {
|
||||
if (activity != null && !activity.isDestroyed()) {
|
||||
Glide.with(activity.getApplicationContext()).load(url).error(drawable).into(imageView);
|
||||
} else {
|
||||
Log.i(TAG, "Picture loading failed,context is null");
|
||||
}
|
||||
}
|
||||
|
||||
public void glideLoad(Context context, String url, ImageView imageView) {
|
||||
if (context != null) {
|
||||
Glide.with(context).load(url).into(imageView);
|
||||
} else {
|
||||
Log.i(TAG, "Picture loading failed,context is null");
|
||||
}
|
||||
}
|
||||
|
||||
public void glideLoad(Context context, int drawableId, ImageView imageView) {
|
||||
if (context != null) {
|
||||
Glide.with(context).load(context.getDrawable(drawableId)).centerCrop().into(imageView);
|
||||
} else {
|
||||
Log.i(TAG, "Picture loading failed,context is null");
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
public void glideLoad(Activity activity, String url, ImageView imageView, int default_image) {
|
||||
if (!activity.isDestroyed()) {
|
||||
// Glide.with(activity).load(url).centerCrop().dontAnimate().error(default_image).into(imageView);
|
||||
Glide.with(activity).load(url).into(new SimpleTarget<Drawable>() {
|
||||
@Override
|
||||
public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
|
||||
imageView.setImageDrawable(resource);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Log.i(TAG, "Picture loading failed,activity is Destroyed");
|
||||
}
|
||||
}
|
||||
|
||||
public void glideLoad(Fragment fragment, String url, ImageView imageView, int default_image) {
|
||||
if (fragment != null && fragment.getActivity() != null) {
|
||||
Glide.with(fragment).load(url).centerCrop().error(default_image).into(imageView);
|
||||
} else {
|
||||
Log.i(TAG, "Picture loading failed,fragment is null");
|
||||
}
|
||||
}
|
||||
|
||||
public void glideLoad(android.app.Fragment fragment, String url, ImageView imageView, int default_image) {
|
||||
if (fragment != null && fragment.getActivity() != null) {
|
||||
Glide.with(fragment).load(url).centerCrop().error(default_image).into(imageView);
|
||||
} else {
|
||||
Log.i(TAG, "Picture loading failed,android.app.Fragment is null");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.ttstd.template.view;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.databinding.BindingAdapter;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.ttstd.template.R;
|
||||
import com.ttstd.template.utils.GlideLoadUtils;
|
||||
|
||||
public class DataBindingAdapter {
|
||||
@BindingAdapter("android:src")
|
||||
public static void setSrc(ImageView view, Bitmap bitmap) {
|
||||
view.setImageBitmap(bitmap);
|
||||
}
|
||||
|
||||
@BindingAdapter("android:src")
|
||||
public static void setSrc(ImageView view, int resId) {
|
||||
view.setImageResource(resId);
|
||||
}
|
||||
|
||||
@BindingAdapter("imageUrl")
|
||||
public static void setSrc(ImageView imageView, String url) {
|
||||
Glide.with(imageView.getContext())
|
||||
.load(url)
|
||||
.error(R.mipmap.ic_launcher)
|
||||
.centerCrop()
|
||||
.into(imageView);
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义设置图片属性 - 在匹配时自定义命名空间会被忽略
|
||||
*/
|
||||
@BindingAdapter({"imageUrl", "error"})
|
||||
public static void loadImage(ImageView imageView, String url, Drawable error) {
|
||||
GlideLoadUtils.getInstance().glideLoadc(imageView.getContext(), url, imageView, error);
|
||||
}
|
||||
|
||||
@BindingAdapter({"loadUrl"})
|
||||
public static void loadUrl(ImageView imageView, String url) {
|
||||
if (TextUtils.isEmpty(url)) {
|
||||
imageView.setVisibility(View.GONE);
|
||||
} else {
|
||||
imageView.setVisibility(View.VISIBLE);
|
||||
Glide.with(imageView.getContext())
|
||||
.load(url)
|
||||
.into(imageView);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,22 @@
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".activity.main.MainActivity">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/content"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/bt_mvp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="mvp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/bt_mvvm"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="mvvm" />
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
21
app/src/main/res/layout/activity_mvvm.xml
Normal file
21
app/src/main/res/layout/activity_mvvm.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context=".activity.main.MainActivity">
|
||||
|
||||
<data>
|
||||
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
@@ -6,13 +6,36 @@
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
<item name="android:fitsSystemWindows">true</item>
|
||||
</style>
|
||||
|
||||
<!-- <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">-->
|
||||
<!-- <!– Customize your theme here. –>-->
|
||||
<!-- <item name="colorPrimary">@color/colorPrimary</item>-->
|
||||
<!-- <item name="colorPrimaryDark">@color/colorPrimaryDark</item>-->
|
||||
<!-- <item name="colorAccent">@color/colorAccent</item>-->
|
||||
<!-- </style>-->
|
||||
<!-- <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">-->
|
||||
<!-- <!– Customize your theme here. –>-->
|
||||
<!-- <item name="colorPrimary">@color/colorPrimary</item>-->
|
||||
<!-- <item name="colorPrimaryDark">@color/colorPrimaryDark</item>-->
|
||||
<!-- <item name="colorAccent">@color/colorAccent</item>-->
|
||||
<!-- </style>-->
|
||||
|
||||
</resources>
|
||||
<style name="activity_styles" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- <item name="android:windowFullscreen">true</item>-->
|
||||
<!--设置dialog的背景-->
|
||||
<item name="android:windowBackground">@android:color/transparent</item>
|
||||
<!--设置Dialog的windowFrame框为无-->
|
||||
<item name="android:windowFrame">@null</item>
|
||||
<!--设置无标题-->
|
||||
<item name="windowNoTitle">true</item>
|
||||
<!--是否浮现在activity之上-->
|
||||
<!--为false会导致windowCloseOnTouchOutside
|
||||
失效-->
|
||||
<item name="android:windowIsFloating">true</item>
|
||||
<!--是否半透明-->
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
<!--设置窗口内容不覆盖-->
|
||||
<item name="android:windowContentOverlay">@null</item>
|
||||
<!--设置动画,在这里使用让它继承系统的Animation.Dialog-->
|
||||
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
|
||||
<!--背景是否模糊显示-->
|
||||
<item name="android:backgroundDimEnabled">true</item>
|
||||
<item name="android:windowCloseOnTouchOutside">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
23
build.gradle
23
build.gradle
@@ -1,18 +1,19 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
|
||||
buildscript {
|
||||
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url "https://jitpack.io" }
|
||||
maven {url 'http://developer.huawei.com/repo/'}
|
||||
maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
|
||||
maven { url 'http://maven.aliyun.com/nexus/content/repositories/releases/' }
|
||||
maven { url 'http://developer.huawei.com/repo/' }
|
||||
maven { url 'https://maven.aliyun.com/repository/central' }
|
||||
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||
maven { url 'https://maven.aliyun.com/repository/google' }
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.6.4'
|
||||
|
||||
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
@@ -20,13 +21,19 @@ buildscript {
|
||||
}
|
||||
|
||||
allprojects {
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
force 'androidx.constraintlayout:constraintlayout:2.0.4'
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven { url "https://jitpack.io" }
|
||||
maven {url 'http://developer.huawei.com/repo/'}
|
||||
maven { url 'http://maven.aliyun.com/nexus/content/repositories/jcenter' }
|
||||
maven { url 'http://maven.aliyun.com/nexus/content/repositories/releases/' }
|
||||
maven { url 'http://developer.huawei.com/repo/' }
|
||||
maven { url 'https://maven.aliyun.com/repository/central' }
|
||||
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||
maven { url 'https://maven.aliyun.com/repository/google' }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user