From fe4fa5323fc075ca7fdf3d6c8cfd20cb0a7d45f8 Mon Sep 17 00:00:00 2001 From: nilupeng <qingingrunt2010@qq.com> Date: Fri, 29 Jul 2022 10:29:50 +0000 Subject: [PATCH] 部分框架优化, 首页登录部分添加 --- app/src/main/java/com/runt/open/mvvm/base/activities/BaseActivity.java | 89 + app/src/main/java/com/runt/open/mvvm/MyApplication.java | 26 app/src/main/res/layout/item_msg.xml | 66 + app/src/main/java/com/runt/open/mvvm/retrofit/utils/RetrofitUtils.java | 3 app/src/main/java/com/runt/open/mvvm/widgets/CornerImageView.java | 163 +++ app/src/main/java/com/runt/open/mvvm/base/model/LoadPageViewModel.java | 47 app/src/main/java/com/runt/open/mvvm/base/model/BaseViewModel.java | 23 app/src/main/java/com/runt/open/mvvm/retrofit/converter/DecryptGsonResponseBodyConverter.java | 6 app/src/main/java/com/runt/open/mvvm/base/model/ImpViewModel.java | 7 app/src/main/res/layout/activity_setting.xml | 79 + app/src/main/java/com/runt/open/mvvm/ui/web/WebViewActivity.java | 51 app/src/main/java/com/runt/open/mvvm/base/fragments/LoadPageFragment.java | 96 + app/src/main/java/com/runt/open/mvvm/ui/login/LoginViewModel.java | 28 app/src/main/java/com/runt/open/mvvm/ui/main/home/HomeFragment.java | 30 app/src/main/res/layout/activity_main.xml | 30 app/src/main/java/com/runt/open/mvvm/ui/splash/SplashViewModel.java | 51 app/build.gradle | 15 app/src/main/res/layout/activity_splash.xml | 4 app/src/main/java/com/runt/open/mvvm/util/DeviceUtil.java | 57 + app/src/main/java/com/runt/open/mvvm/base/adapter/BaseAdapter.java | 146 +- app/src/main/java/com/runt/open/mvvm/ui/main/mine/MineFragment.java | 177 +++ app/src/main/java/com/runt/open/mvvm/retrofit/net/NetWorkListenear.java | 28 app/src/main/java/com/runt/open/mvvm/ui/splash/SplashActivity.java | 79 - app/src/main/res/layout/activity_web.xml | 7 app/src/main/java/com/runt/open/mvvm/ui/main/home/MsgAdapter.java | 33 app/src/main/res/layout/fragment_mine.xml | 191 +++ app/src/main/java/com/runt/open/mvvm/data/Results.java | 6 app/src/main/java/com/runt/open/mvvm/retrofit/net/NetWorkCost.java | 27 app/src/main/res/layout/fragment_service.xml | 126 ++ app/src/main/java/com/runt/open/mvvm/retrofit/utils/HttpPrintUtils.java | 61 app/src/main/res/values/styles.xml | 27 app/src/main/java/com/runt/open/mvvm/base/activities/LoadPageActivity.java | 96 + app/src/main/java/com/runt/open/mvvm/data/PageResult.java | 2 app/src/main/java/com/runt/open/mvvm/widgets/TitleBarView.java | 14 app/src/main/res/layout/refresh_recycler.xml | 2 app/src/main/java/com/runt/open/mvvm/util/HandleDate.java | 216 ++++ app/src/main/java/com/runt/open/mvvm/data/HttpApiResult.java | 2 app/src/main/java/com/runt/open/mvvm/widgets/CircleImageView.java | 245 ++++ app/src/main/java/com/runt/open/mvvm/base/fragments/BaseFragment.java | 44 app/src/main/java/com/runt/open/mvvm/ui/main/mine/MineViewModel.java | 36 app/src/main/java/com/runt/open/mvvm/ui/main/home/Message.java | 8 app/src/main/java/com/runt/open/mvvm/retrofit/Interceptor/HttpLoggingInterceptor.java | 143 +- app/src/main/java/com/runt/open/mvvm/data/ApkUpGradeResult.java | 2 app/src/main/AndroidManifest.xml | 3 app/src/main/java/com/runt/open/mvvm/ui/main/MainActivity.java | 153 ++ app/src/main/java/com/runt/open/mvvm/retrofit/observable/HttpObserver.java | 113 - /dev/null | 25 app/src/main/java/com/runt/open/mvvm/base/activities/BaseTabActivity.java | 4 app/src/main/java/com/runt/open/mvvm/ui/main/home/HomeViewModel.java | 19 app/src/main/java/com/runt/open/mvvm/base/fragments/BaseTabFragment.java | 20 app/src/main/java/com/runt/open/mvvm/retrofit/api/CommonApiCenter.java | 11 app/src/main/java/com/runt/open/mvvm/ui/login/RegisterLoginActivity.java | 138 +- app/src/main/java/com/runt/open/mvvm/ui/main/service/ServiceFragment.java | 63 + 53 files changed, 2,474 insertions(+), 664 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f46abb5..306004b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,16 +18,14 @@ buildTypes { debug{ minifyEnabled false - buildConfigField 'String','HOST_IP_ADDR','"http://192.168.100.82:8080/"' - buildConfigField 'String','ENVIRONMENT','"release"' - resValue "string", "app_name", "MVVM开源项目测试" + buildConfigField 'String','HOST_IP_ADDR','"http://192.168.110.116:8080/"' + resValue "string", "app_name", "MVVM OPEN TEST" proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } release { minifyEnabled false - buildConfigField 'String','HOST_IP_ADDR','"http://192.168.100.82:8080/"' - buildConfigField 'String','ENVIRONMENT','"release"' - resValue "string", "app_name", "MVVM开源项目" + buildConfigField 'String','HOST_IP_ADDR','"http://192.168.100.82:8080/' + resValue "string", "app_name", "MVVM OPEN" proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } @@ -77,9 +75,8 @@ implementation 'com.guolindev.permissionx:permissionx:1.6.0' //权限依赖 implementation 'com.github.bumptech.glide:glide:4.12.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' - implementation 'com.pangle.cn:ads-sdk-pro:4.0.2.2'//字节跳动 穿山甲广告 - implementation 'com.tencent.bugly:crashreport:latest.release' //其中latest.release指代最新Bugly SDK版本号,也可以指定明确的版本号,例如2.1.9 - implementation 'com.tencent.bugly:nativecrashreport:latest.release' //其中latest.release指代最新Bugly NDK版本号,也可以指定明确的版本号,例如3.0 implementation 'com.facebook.rebound:rebound:0.3.6'//Rebound “弹簧”动画效果的第三方工具包,由FaceBook implementation 'com.github.zhaolei9527:BottomMenu:v1.0.1'//底部菜单弹框 + implementation 'com.github.LuckSiege.PictureSelector:picture_library:v2.2.3'//图片选择 + implementation 'com.github.wildma:PictureSelector:1.1.1'//图片选择裁切工具 } \ No newline at end of file diff --git a/app/libs/alipaySdk-15.7.5.aar b/app/libs/alipaySdk-15.7.5.aar deleted file mode 100644 index d977ea2..0000000 --- a/app/libs/alipaySdk-15.7.5.aar +++ /dev/null Binary files differ diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4e8fded..f076df2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -30,6 +30,7 @@ android:label="@string/app_name" android:supportsRtl="true" android:networkSecurityConfig="@xml/network_security_config" + tools:replace="android:theme" android:theme="@style/Theme.OpemMvvm" > <activity android:name=".ui.splash.SplashActivity" @@ -41,7 +42,7 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - <activity android:name=".MainActivity" + <activity android:name=".ui.main.MainActivity" android:launchMode="singleTask" tools:ignore="WrongManifestParent" android:exported="true"> diff --git a/app/src/main/java/com/runt/open/mvvm/MainActivity.java b/app/src/main/java/com/runt/open/mvvm/MainActivity.java deleted file mode 100644 index 1297088..0000000 --- a/app/src/main/java/com/runt/open/mvvm/MainActivity.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.runt.open.mvvm; - -import android.Manifest; -import android.content.Intent; - -import androidx.activity.result.ActivityResult; -import androidx.activity.result.ActivityResultCallback; -import androidx.activity.result.ActivityResultLauncher; -import androidx.activity.result.contract.ActivityResultContracts; -import androidx.navigation.NavController; -import androidx.navigation.Navigation; -import androidx.navigation.ui.NavigationUI; - -import com.permissionx.guolindev.PermissionX; -import com.runt.open.mvvm.base.activities.BaseActivity; -import com.runt.open.mvvm.data.PhoneDevice; -import com.runt.open.mvvm.databinding.ActivityMainBinding; -import com.runt.open.mvvm.listener.ResPonse; -import com.runt.open.mvvm.ui.login.RegisterLoginActivity; -import com.runt.open.mvvm.ui.main.MainViewModel; - -public class MainActivity extends BaseActivity<ActivityMainBinding, MainViewModel> { - - @Override - public void initViews() { - NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_activity_main); - NavigationUI.setupWithNavController(binding.navView, navController); - checkPermission(); - ActivityResultLauncher<Intent> launcher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() { - @Override - public void onActivityResult(ActivityResult result) { - if(result.getResultCode() == RESULT_CODE_SUCESS){ - showToast("登录成功"); - } - } - }); - Intent intent = new Intent(mContext, RegisterLoginActivity.class); - launcher.launch(intent); - } - - private void showPermissionDialog(){ - - showDialog("警告", "软件需要权限才能运行", "申请权限", "退出", new ResPonse() { - @Override - public void doSuccess(Object obj) { - checkPermission(); - } - - @Override - public void doError(Object obj) { - finish(); - System.exit(0); - } - }); - } - private void checkPermission(){ - PermissionX.init(MainActivity.this) - .permissions(Manifest.permission.READ_PHONE_STATE) - .request((allGranted, grantedList, deniedList) -> { - if(allGranted){ - PhoneDevice.setDevice(mContext); - }else{ - showPermissionDialog(); - } - - }); - } -} \ No newline at end of file diff --git a/app/src/main/java/com/runt/open/mvvm/MyApplication.java b/app/src/main/java/com/runt/open/mvvm/MyApplication.java index 30f98b9..2e7179a 100644 --- a/app/src/main/java/com/runt/open/mvvm/MyApplication.java +++ b/app/src/main/java/com/runt/open/mvvm/MyApplication.java @@ -8,9 +8,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.bytedance.sdk.openadsdk.TTAdConfig; -import com.bytedance.sdk.openadsdk.TTAdConstant; -import com.bytedance.sdk.openadsdk.TTAdSdk; import com.runt.open.mvvm.listener.CrashHandler; import com.runt.open.mvvm.util.MyLog; import com.scwang.smart.refresh.footer.ClassicsFooter; @@ -21,7 +18,6 @@ import com.scwang.smart.refresh.layout.api.RefreshLayout; import com.scwang.smart.refresh.layout.listener.DefaultRefreshFooterCreator; import com.scwang.smart.refresh.layout.listener.DefaultRefreshHeaderCreator; -import com.tencent.bugly.crashreport.CrashReport; import java.util.ArrayList; import java.util.List; @@ -115,29 +111,7 @@ } } }); - CrashReport.initCrashReport(getApplicationContext(), "8d88679ae9", false);//注册bugly - TTAdConfig.Builder builder = new TTAdConfig.Builder() - .appId("5106813") - .useTextureView(true) //使用TextureView控件播放视频,默认为SurfaceView,当有SurfaceView冲突的场景,可以使用TextureView - .appName(getString(R.string.app_name)) - .titleBarTheme(TTAdConstant.TITLE_BAR_THEME_DARK) - .allowShowNotify(true) //是否允许sdk展示通知栏提示 - .allowShowPageWhenScreenLock(true) //是否在锁屏场景支持展示广告落地页 - .directDownloadNetworkType(TTAdConstant.NETWORK_STATE_WIFI) //允许直接下载的网络状态集合 - .supportMultiProcess(true) //是否支持多进程,true支持 - .asyncInit(true) ;//异步初始化sdk,开启可减少初始化耗时 - //.httpStack(new MyOkStack3())//自定义网络库,demo中给出了okhttp3版本的样例,其余请自行开发或者咨询工作人员。 - TTAdSdk.init(this, builder.build(), new TTAdSdk.InitCallback() { - @Override - public void success() { - MyLog.i(TAG,"TTAdSdk success"); - } - @Override - public void fail(int i, String s) { - MyLog.e(TAG,"TTAdSdk fail"); - } - }); CrashHandler crashHandler = CrashHandler.getInstance(); crashHandler.init(getApplicationContext(), new CrashHandler.CrashListener() { @Override diff --git a/app/src/main/java/com/runt/open/mvvm/base/activities/BaseActivity.java b/app/src/main/java/com/runt/open/mvvm/base/activities/BaseActivity.java index 1629d1c..a7d4c8d 100644 --- a/app/src/main/java/com/runt/open/mvvm/base/activities/BaseActivity.java +++ b/app/src/main/java/com/runt/open/mvvm/base/activities/BaseActivity.java @@ -3,13 +3,17 @@ import android.Manifest; import android.app.AlertDialog; import android.content.Context; +import android.content.Intent; import android.content.pm.ActivityInfo; +import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.WindowManager; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; @@ -23,12 +27,14 @@ import androidx.lifecycle.ViewModelProvider; import androidx.viewbinding.ViewBinding; +import com.permissionx.guolindev.PermissionX; import com.runt.open.mvvm.MyApplication; import com.runt.open.mvvm.R; import com.runt.open.mvvm.base.model.BaseViewModel; import com.runt.open.mvvm.base.model.ViewModelFactory; import com.runt.open.mvvm.listener.ResPonse; import com.runt.open.mvvm.util.PreferencesUtils; +import com.runt.open.mvvm.widgets.TitleBarView; import java.io.File; import java.lang.reflect.Method; @@ -41,13 +47,12 @@ * activity 封装 * Created by Administrator on 2021/10/27 0027. */ -public abstract class BaseActivity<B extends ViewBinding,VM extends BaseViewModel> extends AppCompatActivity { +public abstract class BaseActivity<VB extends ViewBinding,VM extends BaseViewModel> extends AppCompatActivity { - protected B binding; - protected VM viewModel; + protected VB mBinding; + protected VM mViewModel; protected String TAG ; public final String[] FILE_PERMISSIONS = new String []{Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.WRITE_EXTERNAL_STORAGE}; - public final String[] LOCATION_PERMISSIONS = new String []{Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION}; public final String[] CAMERA_PERMISSIONS = new String[]{ FILE_PERMISSIONS[0],FILE_PERMISSIONS[1], Manifest.permission.CAMERA}; public final String[] CAMERA_RECORD_PERMISSIONS = new String[]{ FILE_PERMISSIONS[0],FILE_PERMISSIONS[1], Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO}; @@ -83,6 +88,7 @@ RESULT_CODE_SUCESS = 4046/*成功*/, RESULT_CODE_CANCEL = 4043/*取消*/; protected Context mContext; + TitleBarView titleBarView; @Override @@ -93,15 +99,17 @@ setStatusBarTextColor(true); final ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); try { - Class<B> entityClass = (Class<B>) type.getActualTypeArguments()[0]; + Class<VB> entityClass = (Class<VB>) type.getActualTypeArguments()[0]; Method method = entityClass.getMethod("inflate", LayoutInflater.class);//get method from name "inflate"; - binding = (B) method.invoke(entityClass,getLayoutInflater());//execute method to create a objct of viewbind; + mBinding = (VB) method.invoke(entityClass,getLayoutInflater());//execute method to create a objct of viewbind; + titleBarView = (TitleBarView) mBinding.getClass().getDeclaredField("titleBar").get(mBinding); + titleBarView.setLeftClick(v -> onBackPressed()); } catch (Exception e) { e.printStackTrace(); } Class<VM> vmClass = (Class<VM>) type.getActualTypeArguments()[1]; - viewModel = new ViewModelProvider(this,getViewModelFactory()).get(vmClass); - setContentView(binding.getRoot()); + mViewModel = new ViewModelProvider(this,getViewModelFactory()).get(vmClass); + setContentView(mBinding.getRoot()); mContext = this; try { //设置坚屏 一定要放到try catch里面,否则会崩溃 @@ -110,13 +118,34 @@ } TAG = this.getClass().getSimpleName(); initViews(); + mViewModel.onCreate(this); + loadData(); } public abstract void initViews(); + public abstract void loadData(); public boolean isNull(Object object){ return object == null || object.toString().trim().equals("") || object.equals("null"); + } + + protected void setTitle(String text){ + titleBarView.setTitleText(text); + } + + protected void onTitleLeftClick(){ + onBackKeyDown(); + } + + protected void setTitleRight(String text){ + titleBarView.setRightText(text); + titleBarView.setRightDra(null); + } + + protected void setTitleRight(Drawable drawable){ + titleBarView.setRightText(null); + titleBarView.setRightDra(drawable); } @@ -125,11 +154,29 @@ * 显示弹框 * @param title * @param msg + * @param resPonse + */ + public void showDialog(String title,String msg,ResPonse resPonse){ + showDialog(title,msg,"确认","取消",resPonse); + } + + public void showInputDialog(String title,String msg,String hint,ResPonse resPonse){ + showInputDialog(title,msg,hint,"确认","取消",resPonse); + } + + public void showInputDialog(String title, String msg, String hint,String btnOk,String btnCancel,final ResPonse resPonse){ + showDialog(title,msg,hint,btnOk,btnCancel,resPonse,true); + } + + /** + * 显示弹框 + * @param title + * @param msg * @param btnOk * @param btnCancel * @param resPonse */ - public void showDialog(String title, String msg, String btnOk,String btnCancel,final ResPonse resPonse){ + public void showDialog(String title, String msg, String btnOk,String btnCancel,final ResPonse resPonse){ showDialog(title,msg,null,btnOk,btnCancel,resPonse,false); } @@ -215,6 +262,9 @@ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); setStatusBarTextColor(isBlack); + final ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) titleBarView.getLayoutParams(); + layoutParams.topMargin = layoutParams.topMargin+getStatusBarHeight(); + titleBarView.setLayoutParams(layoutParams); } /** @@ -343,7 +393,7 @@ } } public void showToast(String message){ - Toast.makeText(this,message,Toast.LENGTH_SHORT).show(); + runOnUiThread(() -> Toast.makeText(mContext,message,Toast.LENGTH_SHORT).show()); } public void showToast(@StringRes int msg){ @@ -371,6 +421,25 @@ return false; } + /** + * 拨打电话(直接拨打电话) + * @param phoneNum 电话号码 + */ + public void callPhone(String phoneNum){ + PermissionX.init(this) + .permissions(Manifest.permission.CALL_PHONE) + .request((allGranted, grantedList, deniedList) -> { + if(allGranted){ + Intent intent = new Intent(Intent.ACTION_CALL); + Uri data = Uri.parse("tel:" + phoneNum); + intent.setData(data); + startActivity(intent); + }else{ + showToast("权限被拒绝"); + } + }); + } + public boolean getBooleanUserPrefrence(String key){ return PreferencesUtils.getBoolean(this,key,false,PreferencesUtils.USER); diff --git a/app/src/main/java/com/runt/open/mvvm/base/activities/BaseLoadPageActivity.java b/app/src/main/java/com/runt/open/mvvm/base/activities/BaseLoadPageActivity.java deleted file mode 100644 index 9e2695a..0000000 --- a/app/src/main/java/com/runt/open/mvvm/base/activities/BaseLoadPageActivity.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.runt.open.mvvm.base.activities; - -import android.os.Bundle; - -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import androidx.viewbinding.ViewBinding; - -import com.runt.open.mvvm.base.adapter.BaseAdapter; -import com.runt.open.mvvm.base.model.BaseLoadPageViewModel; -import com.runt.open.mvvm.data.BasePageResult; -import com.runt.open.mvvm.databinding.RefreshRecyclerBinding; -import com.scwang.smart.refresh.footer.ClassicsFooter; -import com.scwang.smart.refresh.header.ClassicsHeader; -import com.scwang.smart.refresh.layout.SmartRefreshLayout; -import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener; - -import java.lang.reflect.ParameterizedType; -import java.util.HashMap; - -/** - * Created by Administrator on 2021/11/4 0004. - */ -public abstract class BaseLoadPageActivity<B extends ViewBinding,VM extends BaseLoadPageViewModel,A extends BaseAdapter,D extends BasePageResult> - extends BaseTitleBarActivity<B,VM> implements OnRefreshLoadMoreListener { - - protected SmartRefreshLayout smartRefresh; - protected RecyclerView recycler; - final String TAG = "RecyclerFragment"; - protected A adapter;//适配器 - protected String url;//请求地址 - protected HashMap param;//参数 - protected int page=1; - protected final int SIZE = 10; - protected boolean isRefresh = false;//是否正在刷新 - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - try { - Class<A> entityClass = (Class<A>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[2]; - this.adapter = entityClass.newInstance();//实例化泛型 - String smartStr = "smartRefresh"; - smartRefresh = (SmartRefreshLayout) binding.getClass().getField(smartStr).get(binding); - recycler = (RecyclerView) binding.getClass().getDeclaredField("recycler").get(binding); - } catch (NoSuchFieldException e) { - try { - RefreshRecyclerBinding includeRefreshRecycler = (RefreshRecyclerBinding) binding.getClass().getDeclaredField ("includeRefreshRecycler").get(binding); - smartRefresh = includeRefreshRecycler.smartRefresh; - recycler = includeRefreshRecycler.recycler; - } catch (Exception e2) { - e2.printStackTrace(); - } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InstantiationException e) { - e.printStackTrace(); - } - smartRefresh.setRefreshHeader(new ClassicsHeader(mContext)); - smartRefresh.setRefreshFooter(new ClassicsFooter(mContext)); - smartRefresh.setOnRefreshLoadMoreListener(this); - recycler.setLayoutManager(new LinearLayoutManager(mContext)); - recycler.setAdapter(adapter); - } - - private void finishFreshLoadmore(D result){ - if(result.code == 200){ - - smartRefresh.setEnableRefresh(true); - smartRefresh.finishRefresh(); - if(page == 1){ - adapter.getData().clear(); - adapter.setData(result.rows); - }else{ - adapter.getData().addAll(result.rows); - adapter.notifyDataSetChanged(); - } - if(result.total <= adapter.getData().size()// 总数是否已经加载完 - || result.rows.size() < SIZE // 最后一页数据的数量一般不满size - ){//判断是否没有数据了 - smartRefresh.finishLoadMoreWithNoMoreData(); - }else { - smartRefresh.finishLoadMore(); - } - }else{ - smartRefresh.setEnableRefresh(true); - smartRefresh.finishRefresh(); - smartRefresh.finishLoadMore(); - } - } - - public A getAdapter() { - return adapter; - } -} diff --git a/app/src/main/java/com/runt/open/mvvm/base/activities/BaseTabActivity.java b/app/src/main/java/com/runt/open/mvvm/base/activities/BaseTabActivity.java index c14ee7b..e02d83c 100644 --- a/app/src/main/java/com/runt/open/mvvm/base/activities/BaseTabActivity.java +++ b/app/src/main/java/com/runt/open/mvvm/base/activities/BaseTabActivity.java @@ -35,8 +35,8 @@ //设置当前可见Item左右可见page数,次范围内不会被销毁 //禁用预加载 try { - viewPager2 = (ViewPager2) binding.getClass().getDeclaredField("viewPager2").get(binding); - tabLayout = (TabLayout) binding.getClass().getDeclaredField("tabLayout").get(binding); + viewPager2 = (ViewPager2) mBinding.getClass().getDeclaredField("viewPager2").get(mBinding); + tabLayout = (TabLayout) mBinding.getClass().getDeclaredField("tabLayout").get(mBinding); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { diff --git a/app/src/main/java/com/runt/open/mvvm/base/activities/BaseTitleBarActivity.java b/app/src/main/java/com/runt/open/mvvm/base/activities/BaseTitleBarActivity.java deleted file mode 100644 index 414103e..0000000 --- a/app/src/main/java/com/runt/open/mvvm/base/activities/BaseTitleBarActivity.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.runt.open.mvvm.base.activities; - -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.view.ViewGroup; - -import androidx.annotation.Nullable; -import androidx.viewbinding.ViewBinding; - -import com.runt.open.mvvm.base.model.BaseViewModel; -import com.runt.open.mvvm.widgets.TitleBarView; - -/** - * 带有标题栏的activity封装 - * Created by Administrator on 2021/11/2 0002. - */ -public abstract class BaseTitleBarActivity<B extends ViewBinding,VM extends BaseViewModel> extends BaseActivity<B,VM> { - TitleBarView titleBarView; - - @Override - protected void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - try { - titleBarView = (TitleBarView) binding.getClass().getDeclaredField("titleBar").get(binding); - titleBarView.setLeftClick(v -> onTitleLeftClick()); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (NoSuchFieldException e) { - e.printStackTrace(); - } - } - - protected void setTitle(String text){ - titleBarView.setTitleText(text); - } - - protected void onTitleLeftClick(){ - onBackKeyDown(); - } - - protected void setTitleRight(String text){ - titleBarView.setRightText(text); - titleBarView.setRightDra(null); - } - - protected void setTitleRight(Drawable drawable){ - titleBarView.setRightText(null); - titleBarView.setRightDra(drawable); - } - - @Override - public void setStatusBarTransparent(boolean isBlack) { - super.setStatusBarTransparent(isBlack); - final ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) titleBarView.getLayoutParams(); - layoutParams.topMargin = layoutParams.topMargin+getStatusBarHeight(); - titleBarView.setLayoutParams(layoutParams); - - } -} diff --git a/app/src/main/java/com/runt/open/mvvm/base/activities/LoadPageActivity.java b/app/src/main/java/com/runt/open/mvvm/base/activities/LoadPageActivity.java new file mode 100644 index 0000000..58a319a --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/base/activities/LoadPageActivity.java @@ -0,0 +1,96 @@ +package com.runt.open.mvvm.base.activities; + +import androidx.annotation.NonNull; +import androidx.lifecycle.Observer; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewbinding.ViewBinding; + +import com.runt.open.mvvm.R; +import com.runt.open.mvvm.base.adapter.BaseAdapter; +import com.runt.open.mvvm.base.model.LoadPageViewModel; +import com.scwang.smart.refresh.footer.ClassicsFooter; +import com.scwang.smart.refresh.header.ClassicsHeader; +import com.scwang.smart.refresh.layout.SmartRefreshLayout; +import com.scwang.smart.refresh.layout.api.RefreshLayout; +import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener; + +import java.lang.reflect.ParameterizedType; +import java.util.List; +import java.util.Map; + +/** + * Created by Administrator on 2021/11/4 0004. + */ +public abstract class LoadPageActivity<VB extends ViewBinding,VM extends LoadPageViewModel,A extends BaseAdapter,RESULT> + extends BaseActivity<VB,VM> implements OnRefreshLoadMoreListener { + protected int page; + protected SmartRefreshLayout refresh; + //适配器 + protected A adapter; + + @Override + public void initViews() { + try { + Class<A> entityClass = (Class<A>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[2]; + this.adapter = entityClass.newInstance();//实例化泛型 + } catch (Exception e) { + e.printStackTrace(); + } + refresh.setRefreshHeader(new ClassicsHeader(mContext)); + refresh.setRefreshFooter(new ClassicsFooter(mContext)); + refresh.setOnRefreshLoadMoreListener(this); + RecyclerView recycler = mBinding.getRoot().findViewById(R.id.recycler); + recycler.setLayoutManager(new LinearLayoutManager(mContext)); + recycler.setAdapter(adapter); + refresh = mBinding.getRoot().findViewById(R.id.refresh); + refresh.setOnRefreshLoadMoreListener(this); + mViewModel.getLiveData().observe(this, (Observer<List<RESULT>>) list -> { + adapter.showNull = true; + if(page == 0){ + adapter.setData(list); + }else{ + adapter.addData(list); + } + refresh.finishRefresh(); + //加载完毕 + if(list.size() < 10 || page > 0 && list.size() == 0){ + refresh.finishLoadMoreWithNoMoreData(); + }else{ + refresh.finishLoadMore(); + } + }); + mViewModel.getLiveFailed().observe(this, o -> { + refresh.finishRefresh(); + refresh.finishLoadMore(); + //校正page数值 + int size = adapter.getData().size(); + if(size/mViewModel.SIZE+1 < page){ + page--; + } + }); + } + + @Override + public void loadData() { + refresh.autoRefresh(); + } + + protected abstract Map requestParams(); + + @Override + public void onRefresh(@NonNull RefreshLayout refreshLayout) { + page = 0; + mViewModel.requestData(page,requestParams()); + } + + @Override + public void onLoadMore(@NonNull RefreshLayout refreshLayout) { + page++; + mViewModel.requestData(page,requestParams()); + } + + public A getAdapter() { + return adapter; + } +} diff --git a/app/src/main/java/com/runt/open/mvvm/base/adapter/BaseAdapter.java b/app/src/main/java/com/runt/open/mvvm/base/adapter/BaseAdapter.java index d022444..755f0ee 100644 --- a/app/src/main/java/com/runt/open/mvvm/base/adapter/BaseAdapter.java +++ b/app/src/main/java/com/runt/open/mvvm/base/adapter/BaseAdapter.java @@ -1,6 +1,6 @@ package com.runt.open.mvvm.base.adapter; -import android.graphics.drawable.Drawable; +import android.util.Log; import android.view.LayoutInflater; import android.view.ViewGroup; @@ -8,7 +8,6 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.viewbinding.ViewBinding; -import com.runt.open.mvvm.base.activities.BaseActivity; import com.runt.open.mvvm.databinding.LayoutNullBinding; import com.runt.open.mvvm.util.DeviceUtil; @@ -23,47 +22,73 @@ * T 数据类型 * V 适配器视图 */ -public abstract class BaseAdapter<B extends ViewBinding,T> extends RecyclerView.Adapter { +public abstract class BaseAdapter<DATA, VB extends ViewBinding> extends RecyclerView.Adapter<RecyclerView.ViewHolder> { - protected List<T> mData = new ArrayList<>(); + protected List<DATA> dataList = new ArrayList<>(); + protected OnItemClickListener<DATA> onItemClickListener; + public boolean showNull; + public float defaultMarginBottom,lastMarginBottom; - protected Drawable nullDrawable; - protected String nullTxt="暂无数据"; - protected String TAG = "BaseAdapter"; - protected BaseActivity activity; - - public BaseAdapter(){ + public interface OnItemClickListener<DATA>{ + void onItemClick(int position,DATA data); } - public BaseAdapter(@NonNull List<T> data){ - mData = data; + public class ViewBindHolder extends RecyclerView.ViewHolder { + ViewBinding binding; + public ViewBindHolder(ViewBinding binding) { + super(binding.getRoot()); + this.binding = binding; + } } - public List<T> getData() { - return mData; + public void setOnItemClickListener(OnItemClickListener<DATA> onItemClickListener) { + this.onItemClickListener = onItemClickListener; } - public void setData(@NonNull List<T> data){ - mData = data; + public void setData(List<DATA> list){ + if(dataList != list) { + dataList.clear(); + if (list != null) { + dataList.addAll(list); + } + } notifyDataSetChanged(); + } + + public void addData(DATA data){ + if(data != null){ + dataList.add(data); + } + notifyDataSetChanged(); + } + + public void addData(List<DATA> list){ + if (list != null && list.size() > 0) { + this.dataList.addAll(list); + } + notifyDataSetChanged(); + } + + public List<DATA> getData() { + return dataList; } @NonNull @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + public ViewBindHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { if(viewType == 1 ){ // get genericity "B" - Class<B> entityClass = (Class<B>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; try { - /* for(Method method: entityClass.getMethods()){ + Class<VB> entityClass = (Class<VB>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[1]; + /*for(Method method: entityClass.getMethods()){ StringBuilder sb = new StringBuilder(); for(Class type : method.getParameterTypes()){ sb.append(type.getSimpleName()+","); } - Log.e(TAG,String.format("method:%s,return:%s,param:%s",method.getName(),method.getReturnType().getSimpleName(),sb.toString())); + Log.e("BaseAdapter",String.format("method:%s,return:%s,param:%s",method.getName(),method.getReturnType().getSimpleName(),sb.toString())); }*/ Method method = entityClass.getMethod("inflate", LayoutInflater.class,ViewGroup.class,boolean.class);//get method from name "inflate"; - B vBind = (B) method.invoke(entityClass,LayoutInflater.from(parent.getContext()),parent,false);//execute method to create a objct of viewbind; + VB vBind = (VB) method.invoke(entityClass,LayoutInflater.from(parent.getContext()),parent,false);//execute method to create a objct of viewbind; return new ViewBindHolder(vBind); } catch (SecurityException e) { e.printStackTrace(); @@ -80,19 +105,24 @@ e.printStackTrace(); } } - return new NullViewHolder( LayoutNullBinding.inflate(LayoutInflater.from(parent.getContext()),parent,false)); + return new ViewBindHolder( LayoutNullBinding.inflate( LayoutInflater.from(parent.getContext()), parent, false ) ); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { - //MyLog.i(TAG,"onBindViewHolder position:"+position+" "+mData.size()+" "+getItemViewType(position)); - if(activity == null){ - activity = (BaseActivity) holder.itemView.getContext(); - } - if(getItemViewType(position)==0){ - bindView((NullViewHolder) holder); - }else { - bindView((ViewBindHolder) holder, mData.size() == 0 ? null : mData.get(position), position); + ViewBindHolder bindHolder = (ViewBindHolder) holder; + if(getItemViewType(position) == 0 || bindHolder.binding instanceof LayoutNullBinding){ + onBindEmptyView((LayoutNullBinding) bindHolder.binding); + }else{ + if (onItemClickListener != null) { + bindHolder.binding.getRoot().setOnClickListener(view -> { + if(onItemClickListener != null){ + onItemClickListener.onItemClick(position,getItem(position)); + } + }); + } + onBindView((VB) bindHolder.binding, position, getItem(position)); + setBottomMargin(bindHolder,position); } } @@ -102,7 +132,7 @@ * @param position */ protected void setBottomMargin(ViewBindHolder holder, int position){ - setBottomMargin(holder,position,23); + setBottomMargin(holder,position,lastMarginBottom); } /** @@ -111,56 +141,54 @@ * @param position 位置 * @param dp 间距 */ - protected void setBottomMargin(RecyclerView.ViewHolder holder, int position,int dp){ - setBottomMargin(holder,position,dp,0); + protected void setBottomMargin(RecyclerView.ViewHolder holder, int position,float dp){ + setBottomMargin(holder,position,dp,defaultMarginBottom); } - protected void setBottomMargin(RecyclerView.ViewHolder holder, int position, int dp, int defaultDp){ + + protected void setBottomMargin(RecyclerView.ViewHolder holder, int position, float dp, float defaultDp){ ViewGroup.MarginLayoutParams params1 = (ViewGroup.MarginLayoutParams) holder.itemView.getLayoutParams(); - if(position == mData.size() -1){ + if(position == dataList.size() -1){ params1.setMargins(params1.leftMargin, params1.topMargin, params1.rightMargin, DeviceUtil.convertDpToPixel(dp,holder.itemView.getContext())); }else{ params1.setMargins(params1.leftMargin, params1.topMargin, params1.rightMargin, DeviceUtil.convertDpToPixel(defaultDp,holder.itemView.getContext())); } } - protected abstract void bindView(ViewBindHolder holder,T data,int position); - protected void bindView(NullViewHolder holder){ - - } - + /** + * 空数据支持 + * @return + */ @Override public int getItemCount() { - //默认显示空视图,若不显示空视图则重写该方法,返回mData.size() - return mData == null || mData.size() == 0 ?1:mData.size(); + return (showNull && dataList.size() == 0 )? 1 : dataList.size(); } - + /** + * 当下标为0,数据集合为0 返回0(意味当前应显示空数据视图)) + * @param position + * @return + */ @Override public int getItemViewType(int position) { - //当下标为0,数据集合为0 返回0(意味当前应显示空数据视图)) - //MyLog.i(TAG,"getItemViewType position:"+position+" mdata:"+mData.size()+" "+(position ==0 && mData.size()==0)); - return position == 0 && mData.size()==0?0:1; + return (showNull && position == 0 && dataList.size() == 0)? 0 : 1; } - public class ViewBindHolder extends RecyclerView.ViewHolder{ - public B binding; - public ViewBindHolder( B binding) { - super(binding.getRoot()); - this.binding = binding; + public DATA getItem(int position){ + if(position >= dataList.size()){ + return null; + }else { + return dataList.get(position); } } + + protected abstract void onBindView(VB binding, int position, DATA data); + /** * 空数据显示 - * Created by Administrator on 2021/10/28 0028. */ - public class NullViewHolder extends RecyclerView.ViewHolder { - LayoutNullBinding binding; + protected void onBindEmptyView(LayoutNullBinding emptyBinding){ + Log.e("baseAdapter"," emptyBinding:"+emptyBinding); - public NullViewHolder(LayoutNullBinding binding) { - super(binding.getRoot()); - this.binding = binding; - } } - } diff --git a/app/src/main/java/com/runt/open/mvvm/base/fragments/BaseFragment.java b/app/src/main/java/com/runt/open/mvvm/base/fragments/BaseFragment.java index 04fab76..5918601 100644 --- a/app/src/main/java/com/runt/open/mvvm/base/fragments/BaseFragment.java +++ b/app/src/main/java/com/runt/open/mvvm/base/fragments/BaseFragment.java @@ -7,11 +7,11 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; -import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModelProvider; import androidx.viewbinding.ViewBinding; import com.runt.open.mvvm.base.activities.BaseActivity; +import com.runt.open.mvvm.base.model.BaseViewModel; import com.runt.open.mvvm.base.model.ViewModelFactory; import java.lang.reflect.Method; @@ -21,11 +21,22 @@ * fragment 封装 * Created by Administrator on 2021/10/28 0028. */ -public abstract class BaseFragment<B extends ViewBinding,VM extends ViewModel> extends Fragment { +public abstract class BaseFragment<VB extends ViewBinding,VM extends BaseViewModel> extends Fragment { - protected BaseActivity activity; - protected B binding; - protected VM viewModel; + protected BaseActivity mActivity; + protected VB mBinding; + protected VM mViewModel; + public static final int REQUEST_CODE_LOGOUT = 20009,/*退出*/ + REQUEST_CODE_ORDER = 10010,/*订单详情*/ + REQUEST_CODE_LOGIN = 20010,/*登录*/ + REQUEST_CODE_SCAN = 20011/*扫描请求*/, + REQUEST_CODE_PIC = 20012,/*选择图片*/ + REQUEST_CODE_PERMISSION = 20013,/*请求权限*/ + REQUEST_CODE_SIGN = 20014,/*签到*/ + REQUEST_CODE_WITHDRAW = 22014,/*提现*/ + RESULT_CODE_FAILD = 4044/*失败*/, + RESULT_CODE_SUCESS = 4046/*成功*/, + RESULT_CODE_CANCEL = 4043/*取消*/; @Nullable @Override @@ -33,17 +44,23 @@ // get genericity "B" try { final ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass(); - Class<B> entityClass = (Class<B>) type.getActualTypeArguments()[0]; + Class<VB> entityClass = (Class<VB>) type.getActualTypeArguments()[0]; Method method = entityClass.getMethod("inflate", LayoutInflater.class,ViewGroup.class,boolean.class);//get method from name "inflate"; - binding = (B) method.invoke(entityClass,inflater,container,false);//execute method to create a objct of viewbind; + mBinding = (VB) method.invoke(entityClass,inflater,container,false);//execute method to create a objct of viewbind; Class<VM> vmClass = (Class<VM>) type.getActualTypeArguments()[1]; - viewModel = new ViewModelProvider(this,getViewModelFactory()).get(vmClass); + mViewModel = new ViewModelProvider(this,getViewModelFactory()).get(vmClass); } catch (Exception e) { e.printStackTrace(); } - return binding.getRoot(); + initViews(); + return mBinding.getRoot(); } + public void setOnClickListener(View.OnClickListener click,int... ids){ + for (int id: ids){ + getActivity().findViewById(id).setOnClickListener(click); + } + } public ViewModelProvider.Factory getViewModelFactory(){ return ViewModelFactory.getInstance(); } @@ -51,16 +68,19 @@ @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); - activity = (BaseActivity) getActivity(); - initViews(); + mActivity = (BaseActivity) getActivity(); + mViewModel.onCreate(mActivity); + loadData(); } public abstract void initViews(); + public abstract void loadData(); + @Override public void onDestroyView() { super.onDestroyView(); - binding = null; + mBinding = null; } } diff --git a/app/src/main/java/com/runt/open/mvvm/base/fragments/BaseLoadPageFragment.java b/app/src/main/java/com/runt/open/mvvm/base/fragments/BaseLoadPageFragment.java deleted file mode 100644 index 71cb4f2..0000000 --- a/app/src/main/java/com/runt/open/mvvm/base/fragments/BaseLoadPageFragment.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.runt.open.mvvm.base.fragments; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import androidx.viewbinding.ViewBinding; - -import com.runt.open.mvvm.base.adapter.BaseAdapter; -import com.runt.open.mvvm.base.model.BaseLoadPageViewModel; -import com.runt.open.mvvm.data.BasePageResult; -import com.runt.open.mvvm.databinding.RefreshRecyclerBinding; -import com.scwang.smart.refresh.footer.ClassicsFooter; -import com.scwang.smart.refresh.header.ClassicsHeader; -import com.scwang.smart.refresh.layout.SmartRefreshLayout; -import com.scwang.smart.refresh.layout.api.RefreshLayout; -import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener; - -import java.lang.reflect.ParameterizedType; -import java.util.HashMap; - -/** - * 分页fragment 封装 - * Created by Administrator on 2021/11/3 0003. - */ -public abstract class BaseLoadPageFragment<B extends ViewBinding,VM extends BaseLoadPageViewModel,A extends BaseAdapter,D extends BasePageResult> extends BaseFragment<B,VM> - implements OnRefreshLoadMoreListener { - protected SmartRefreshLayout smartRefresh; - protected RecyclerView recycler; - final String TAG = "RecyclerFragment"; - protected A adapter;//适配器 - protected String url;//请求地址 - protected HashMap param;//参数 - protected int page=1; - protected final int SIZE = 10; - protected boolean isRefresh = false;//是否正在刷新 - - @Override - public void initViews() { - try { - Class<A> entityClass = (Class<A>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[2]; - this.adapter = entityClass.newInstance();//实例化泛型 - String smartStr = "smartRefresh"; - smartRefresh = (SmartRefreshLayout) binding.getClass().getField(smartStr).get(binding); - recycler = (RecyclerView) binding.getClass().getDeclaredField("recycler").get(binding); - } catch (NoSuchFieldException e) { - try { - RefreshRecyclerBinding includeRefreshRecycler = (RefreshRecyclerBinding) binding.getClass().getDeclaredField ("includeRefreshRecycler").get(binding); - smartRefresh = includeRefreshRecycler.smartRefresh; - recycler = includeRefreshRecycler.recycler; - } catch (Exception e2) { - e2.printStackTrace(); - } - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (java.lang.InstantiationException e) { - e.printStackTrace(); - } - smartRefresh.setRefreshHeader(new ClassicsHeader(getContext())); - smartRefresh.setRefreshFooter(new ClassicsFooter(getContext())); - smartRefresh.setOnRefreshLoadMoreListener(this); - recycler.setLayoutManager(new LinearLayoutManager(getContext())); - recycler.setAdapter(adapter); - } - - @Override - public void onLoadMore(@NonNull RefreshLayout refreshLayout) { - page++; - viewModel.onLoadMore(); - } - - @Override - public void onRefresh(@NonNull RefreshLayout refreshLayout) { - page = 1; - viewModel.onRefresh(); - } - - private void finishFreshLoadmore(D result){ - if(result.code == 200){ - - smartRefresh.setEnableRefresh(true); - smartRefresh.finishRefresh(); - if(page == 1){ - adapter.getData().clear(); - adapter.setData(result.rows); - }else{ - adapter.getData().addAll(result.rows); - adapter.notifyDataSetChanged(); - } - if(result.total <= adapter.getData().size()// 总数是否已经加载完 - || result.rows.size() < SIZE // 最后一页数据的数量一般不满size - ){//判断是否没有数据了 - smartRefresh.finishLoadMoreWithNoMoreData(); - }else { - smartRefresh.finishLoadMore(); - } - }else{ - smartRefresh.setEnableRefresh(true); - smartRefresh.finishRefresh(); - smartRefresh.finishLoadMore(); - } - } - - public A getAdapter() { - return adapter; - } -} diff --git a/app/src/main/java/com/runt/open/mvvm/base/fragments/BaseTabFragment.java b/app/src/main/java/com/runt/open/mvvm/base/fragments/BaseTabFragment.java index f482d6b..bf6878f 100644 --- a/app/src/main/java/com/runt/open/mvvm/base/fragments/BaseTabFragment.java +++ b/app/src/main/java/com/runt/open/mvvm/base/fragments/BaseTabFragment.java @@ -1,12 +1,12 @@ package com.runt.open.mvvm.base.fragments; -import androidx.lifecycle.ViewModel; import androidx.viewbinding.ViewBinding; import androidx.viewpager2.widget.ViewPager2; import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayoutMediator; import com.runt.open.mvvm.base.adapter.FragmentAdapter; +import com.runt.open.mvvm.base.model.BaseViewModel; import java.util.ArrayList; import java.util.Arrays; @@ -16,7 +16,7 @@ * 带有tablayout fragment封装 * Created by Administrator on 2021/11/3 0003. */ -public abstract class BaseTabFragment<B extends ViewBinding,VM extends ViewModel> extends BaseFragment<B,VM> { +public abstract class BaseTabFragment<B extends ViewBinding,VM extends BaseViewModel> extends BaseFragment<B,VM> { TabLayout tabLayout; FragmentAdapter fragmentAdapter; @@ -25,28 +25,30 @@ @Override public void initViews() { - - fragmentAdapter = new FragmentAdapter(activity); - fragmentAdapter.setFragments(initFragments()); setTabTitles(initTabTitles()); //设置当前可见Item左右可见page数,次范围内不会被销毁 //禁用预加载 try { - viewPager2 = (ViewPager2) binding.getClass().getDeclaredField("viewPager2").get(binding); - tabLayout = (TabLayout) binding.getClass().getDeclaredField("tabLayout").get(binding); + viewPager2 = (ViewPager2) mBinding.getClass().getDeclaredField("viewPager2").get(mBinding); + tabLayout = (TabLayout) mBinding.getClass().getDeclaredField("tabLayout").get(mBinding); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (NoSuchFieldException e) { e.printStackTrace(); } - ; viewPager2.setOffscreenPageLimit(ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT); - viewPager2.setAdapter(fragmentAdapter); viewPager2.setCurrentItem(0); viewPager2.setUserInputEnabled(false); //true:滑动,false:禁止滑动 new TabLayoutMediator(tabLayout, viewPager2, (tab, position) -> tab.setText(tabTitles.get(position))).attach(); } + @Override + public void loadData() { + fragmentAdapter = new FragmentAdapter(mActivity); + fragmentAdapter.setFragments(initFragments()); + viewPager2.setAdapter(fragmentAdapter); + } + protected abstract List<String> initTabTitles(); protected abstract List<BaseFragment> initFragments(); diff --git a/app/src/main/java/com/runt/open/mvvm/base/fragments/LoadPageFragment.java b/app/src/main/java/com/runt/open/mvvm/base/fragments/LoadPageFragment.java new file mode 100644 index 0000000..d0489f1 --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/base/fragments/LoadPageFragment.java @@ -0,0 +1,96 @@ +package com.runt.open.mvvm.base.fragments; + +import androidx.annotation.NonNull; +import androidx.lifecycle.Observer; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.viewbinding.ViewBinding; + +import com.runt.open.mvvm.R; +import com.runt.open.mvvm.base.adapter.BaseAdapter; +import com.runt.open.mvvm.base.model.LoadPageViewModel; +import com.scwang.smart.refresh.footer.ClassicsFooter; +import com.scwang.smart.refresh.header.ClassicsHeader; +import com.scwang.smart.refresh.layout.SmartRefreshLayout; +import com.scwang.smart.refresh.layout.api.RefreshLayout; +import com.scwang.smart.refresh.layout.listener.OnRefreshLoadMoreListener; + +import java.lang.reflect.ParameterizedType; +import java.util.List; +import java.util.Map; + +/** + * 分页fragment 封装 + * Created by Administrator on 2021/11/3 0003. + */ +public abstract class LoadPageFragment<VB extends ViewBinding,VM extends LoadPageViewModel,A extends BaseAdapter,RESULT> extends BaseFragment<VB,VM> implements OnRefreshLoadMoreListener { + + protected int page; + protected SmartRefreshLayout refresh; + //适配器 + protected A adapter; + + @Override + public void initViews() { + try { + Class<A> entityClass = (Class<A>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[2]; + this.adapter = entityClass.newInstance();//实例化泛型 + } catch (Exception e) { + e.printStackTrace(); + } + RecyclerView recycler = mBinding.getRoot().findViewById(R.id.recycler); + recycler.setLayoutManager(new LinearLayoutManager(getContext())); + recycler.setAdapter(adapter); + refresh = mBinding.getRoot().findViewById(R.id.refresh); + refresh.setRefreshHeader(new ClassicsHeader(getContext())); + refresh.setRefreshFooter(new ClassicsFooter(getContext())); + refresh.setOnRefreshLoadMoreListener(this); + mViewModel.getLiveData().observe(this, (Observer<List<RESULT>>) list -> { + adapter.showNull = true; + if(page == 0){ + adapter.setData(list); + }else{ + adapter.addData(list); + } + refresh.finishRefresh(); + //加载完毕 + if(list.size() < 10 || page > 0 && list.size() == 0){ + refresh.finishLoadMoreWithNoMoreData(); + }else{ + refresh.finishLoadMore(); + } + }); + mViewModel.getLiveFailed().observe(this, o -> { + refresh.finishRefresh(); + refresh.finishLoadMore(); + //校正page数值 + int size = adapter.getData().size(); + if(size/mViewModel.SIZE+1 < page){ + page--; + } + }); + } + + @Override + public void loadData() { + refresh.autoRefresh(); + } + + protected abstract Map requestParams(); + + @Override + public void onRefresh(@NonNull RefreshLayout refreshLayout) { + page = 0; + mViewModel.requestData(page,requestParams()); + } + + @Override + public void onLoadMore(@NonNull RefreshLayout refreshLayout) { + page++; + mViewModel.requestData(page,requestParams()); + } + + public A getAdapter() { + return adapter; + } +} diff --git a/app/src/main/java/com/runt/open/mvvm/base/model/BaseLoadPageViewModel.java b/app/src/main/java/com/runt/open/mvvm/base/model/BaseLoadPageViewModel.java deleted file mode 100644 index 150ef54..0000000 --- a/app/src/main/java/com/runt/open/mvvm/base/model/BaseLoadPageViewModel.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.runt.open.mvvm.base.model; - -/** - * 分页 - * Created by Administrator on 2021/11/3 0003. - */ -public abstract class BaseLoadPageViewModel extends BaseViewModel { - - public abstract void onRefresh(); - - public abstract void onLoadMore(); - -} diff --git a/app/src/main/java/com/runt/open/mvvm/base/model/BaseViewModel.java b/app/src/main/java/com/runt/open/mvvm/base/model/BaseViewModel.java index 3c172a9..de2ed52 100644 --- a/app/src/main/java/com/runt/open/mvvm/base/model/BaseViewModel.java +++ b/app/src/main/java/com/runt/open/mvvm/base/model/BaseViewModel.java @@ -1,13 +1,15 @@ package com.runt.open.mvvm.base.model; -import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; -import com.runt.open.mvvm.data.LoadingCmd; +import com.runt.open.mvvm.base.activities.BaseActivity; import com.runt.open.mvvm.retrofit.AndroidScheduler; +import com.runt.open.mvvm.retrofit.api.CommonApiCenter; import com.runt.open.mvvm.retrofit.observable.HttpObserver; +import com.runt.open.mvvm.retrofit.utils.RetrofitUtils; import io.reactivex.Observable; +import io.reactivex.functions.Consumer; import io.reactivex.schedulers.Schedulers; /** @@ -15,10 +17,11 @@ */ public class BaseViewModel extends ViewModel { - MutableLiveData<LoadingCmd> loadLive = new MutableLiveData<>(); + protected BaseActivity mActivity; + protected CommonApiCenter commonApi = RetrofitUtils.getInstance().getCommonApi(); - public MutableLiveData<LoadingCmd> getLoadLive() { - return loadLive; + public void onCreate(BaseActivity activity) { + this.mActivity = activity; } /** @@ -43,11 +46,17 @@ public <T> void httpObserverOnLoading(Observable<T> observable, HttpObserver observer){ observable.subscribeOn(Schedulers.io())//指定网络请求在io后台线程中进行 .doOnSubscribe(disposable -> { - loadLive.setValue(new LoadingCmd(LoadingCmd.CMD.LOADING,"请求数据中...")); + mActivity.showLoadingDialog(""); }) .observeOn(AndroidScheduler.mainThread()) + .doOnError(new Consumer<Throwable>() { + @Override + public void accept(Throwable throwable) throws Exception { + + } + }) .doOnComplete(() -> { - loadLive.postValue(new LoadingCmd(LoadingCmd.CMD.DISSMISS)); + mActivity.dissmissLoadingDialog(); }) .subscribe(observer); } diff --git a/app/src/main/java/com/runt/open/mvvm/base/model/ImpViewModel.java b/app/src/main/java/com/runt/open/mvvm/base/model/ImpViewModel.java new file mode 100644 index 0000000..985f772 --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/base/model/ImpViewModel.java @@ -0,0 +1,7 @@ +package com.runt.open.mvvm.base.model; + +/** + * @purpose Created by Runt (qingingrunt2010@qq.com) on 2022/7/27. + */ +public class ImpViewModel extends BaseViewModel{ +} diff --git a/app/src/main/java/com/runt/open/mvvm/base/model/LoadPageViewModel.java b/app/src/main/java/com/runt/open/mvvm/base/model/LoadPageViewModel.java new file mode 100644 index 0000000..5560ad5 --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/base/model/LoadPageViewModel.java @@ -0,0 +1,47 @@ +package com.runt.open.mvvm.base.model; + +import androidx.lifecycle.MutableLiveData; + +import com.runt.open.mvvm.data.HttpApiResult; +import com.runt.open.mvvm.data.PageResult; +import com.runt.open.mvvm.retrofit.observable.HttpObserver; + +import java.util.List; +import java.util.Map; + +/** + * 分页 + * Created by Administrator on 2021/11/3 0003. + */ +public abstract class LoadPageViewModel<RESULT extends PageResult> extends BaseViewModel { + + public final int SIZE = 10; + private MutableLiveData<List> liveData = new MutableLiveData<>(); + private MutableLiveData liveFailed = new MutableLiveData(); + + protected abstract String requestUrl(); + + public void requestData(int page,Map param){ + httpObserverOn( commonApi.getPageData(requestUrl(), page, SIZE, param), new HttpObserver<RESULT>() { + + @Override + protected void onSuccess(RESULT data) { + liveData.postValue(data.rows); + } + + @Override + protected void onFailed(HttpApiResult httpResult) { + mActivity.showToast(httpResult.msg); + liveFailed.postValue(1); + } + }); + } + + public MutableLiveData<List> getLiveData(){ + return liveData; + } + + public MutableLiveData getLiveFailed() { + return liveFailed; + } +} diff --git a/app/src/main/java/com/runt/open/mvvm/data/ApkUpGradeResult.java b/app/src/main/java/com/runt/open/mvvm/data/ApkUpGradeResult.java index 6b9d44a..f23882e 100644 --- a/app/src/main/java/com/runt/open/mvvm/data/ApkUpGradeResult.java +++ b/app/src/main/java/com/runt/open/mvvm/data/ApkUpGradeResult.java @@ -3,7 +3,7 @@ /** * Created by Administrator on 2021/11/15 0015. */ -public class ApkUpGradeResult extends BaseApiResult<ApkUpGradeResult.AppInfo>{ +public class ApkUpGradeResult extends HttpApiResult<ApkUpGradeResult.AppInfo> { public class AppInfo { //以下为声明的参数 diff --git a/app/src/main/java/com/runt/open/mvvm/data/BaseApiResult.java b/app/src/main/java/com/runt/open/mvvm/data/HttpApiResult.java similarity index 86% rename from app/src/main/java/com/runt/open/mvvm/data/BaseApiResult.java rename to app/src/main/java/com/runt/open/mvvm/data/HttpApiResult.java index 8ddd410..7e499c8 100644 --- a/app/src/main/java/com/runt/open/mvvm/data/BaseApiResult.java +++ b/app/src/main/java/com/runt/open/mvvm/data/HttpApiResult.java @@ -5,7 +5,7 @@ /** * Created by Administrator on 2021/10/28 0028. */ -public class BaseApiResult<D extends Object> implements Serializable { +public class HttpApiResult<D extends Object> implements Serializable { public String msg; public int code = 200; diff --git a/app/src/main/java/com/runt/open/mvvm/data/LoadingCmd.java b/app/src/main/java/com/runt/open/mvvm/data/LoadingCmd.java deleted file mode 100644 index 1752dea..0000000 --- a/app/src/main/java/com/runt/open/mvvm/data/LoadingCmd.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.runt.open.mvvm.data; - -/** - * My father is Object, ites purpose of - * - * @purpose Created by Runt (qingingrunt2010@qq.com) on 2022/1/28. - */ -public class LoadingCmd { - public CMD code;public String msg; - - public LoadingCmd(CMD code) { - this(code,""); - } - - public LoadingCmd(CMD code, String msg) { - this.code = code; - this.msg = msg; - } - - public enum CMD{LOADING,DISSMISS} -} diff --git a/app/src/main/java/com/runt/open/mvvm/data/BasePageResult.java b/app/src/main/java/com/runt/open/mvvm/data/PageResult.java similarity index 86% rename from app/src/main/java/com/runt/open/mvvm/data/BasePageResult.java rename to app/src/main/java/com/runt/open/mvvm/data/PageResult.java index 6eba4d3..ddf11bd 100644 --- a/app/src/main/java/com/runt/open/mvvm/data/BasePageResult.java +++ b/app/src/main/java/com/runt/open/mvvm/data/PageResult.java @@ -5,7 +5,7 @@ /** * Created by Administrator on 2021/10/28 0028. */ -public class BasePageResult<T> extends BaseApiResult<String>{ +public class PageResult<T> extends HttpApiResult<String> { public int pages; public int total; public int pageNum; diff --git a/app/src/main/java/com/runt/open/mvvm/data/Results.java b/app/src/main/java/com/runt/open/mvvm/data/Results.java index fc55568..0d17e8a 100644 --- a/app/src/main/java/com/runt/open/mvvm/data/Results.java +++ b/app/src/main/java/com/runt/open/mvvm/data/Results.java @@ -1,6 +1,7 @@ package com.runt.open.mvvm.data; import com.runt.open.mvvm.ui.login.UserBean; +import com.runt.open.mvvm.ui.main.home.Message; /** * My father is Object, ites purpose of @@ -9,8 +10,9 @@ */ public class Results { - public static class LoggedInUser extends BaseApiResult<UserBean> { } + public static class LoggedInUser extends HttpApiResult<UserBean> { } - public static class StringApiResult extends BaseApiResult<String>{ } + public static class StringApiResult extends HttpApiResult<String> { } + public class MessageResult extends PageResult<Message>{} } diff --git a/app/src/main/java/com/runt/open/mvvm/retrofit/Interceptor/HttpLoggingInterceptor.java b/app/src/main/java/com/runt/open/mvvm/retrofit/Interceptor/HttpLoggingInterceptor.java index 6d271e4..b0d62f4 100644 --- a/app/src/main/java/com/runt/open/mvvm/retrofit/Interceptor/HttpLoggingInterceptor.java +++ b/app/src/main/java/com/runt/open/mvvm/retrofit/Interceptor/HttpLoggingInterceptor.java @@ -2,11 +2,14 @@ import android.util.Log; +import com.runt.open.mvvm.MyApplication; import com.runt.open.mvvm.retrofit.net.NetWorkCost; import com.runt.open.mvvm.retrofit.net.NetWorkListenear; import com.runt.open.mvvm.retrofit.utils.HttpPrintUtils; -import com.runt.open.mvvm.util.GsonUtils; +import com.runt.open.mvvm.util.DeviceUtil; +import org.json.JSONArray; +import org.json.JSONException; import org.json.JSONObject; import java.io.EOFException; @@ -14,6 +17,7 @@ import java.net.URLDecoder; import java.nio.charset.Charset; import java.util.ArrayList; +import java.util.Date; import java.util.HashMap; import okhttp3.FormBody; @@ -38,47 +42,69 @@ final String TAG = "HttpLogging"; - public HttpLoggingInterceptor() { - } + private boolean printLog ; + public HttpLoggingInterceptor(){ + this(true); + } + public HttpLoggingInterceptor(boolean printLog) { + this.printLog = printLog; + } @Override public Response intercept(Chain chain) throws IOException { - Request request = chain.request(); - int hashCode = request.hashCode(); - ArrayList<String> logArrays = getRequestLog(request); - int position = logArrays.size() +2; - Response response; + Request requestTemp = chain.request(); + int hashCode = requestTemp.hashCode(); + if(printLog) { + Log.d(TAG, "hashcode:" + hashCode); + } + Request.Builder requestBuild = requestTemp.newBuilder() + .addHeader("appVersion", DeviceUtil.getAppVersionName(MyApplication.getApplication())) + .addHeader("os", DeviceUtil.isHarmonyOS()? "harmony" : "android"); + Request request = requestBuild.build().newBuilder().build(); + ArrayList<String> logArrays = new ArrayList<>(); + Response response = null; try { - request = encryptRequest(request);//加密 + logArrays.addAll(getRequestLog(request)); + int position = logArrays.size() +2; + //request = encryptRequest(request);//加密 response = chain.proceed(request); logArrays.addAll(getResponseLog(response)); - Log.d(TAG,"hashcode:"+hashCode); NetWorkCost netWorkCost = NetWorkListenear.workCostMap.get(hashCode); if(netWorkCost != null) { - String cost = String.format("dns:%s,secure:%s,connect:%s,requestH:%s,requestB:%s,responseH:%s,responseB:%s", convertTimes(netWorkCost.dns), convertTimes(netWorkCost.secure), convertTimes(netWorkCost.connect), convertTimes(netWorkCost.requestHeader), convertTimes(netWorkCost.requestBody), convertTimes(netWorkCost.resposeHeader), convertTimes(netWorkCost.resposeBody)); - logArrays.add(position, "<-- costtimes : " + convertTimes(netWorkCost.total) + " (" + cost + ')'); + logArrays.add(position, "<-- costtimes : " + netWorkCost); } NetWorkListenear.workCostMap.remove(hashCode); new Thread(){ @Override public void run() { - HttpPrintUtils.getInstance().printLog(logArrays, true);//线程安全方法,需在新线程执行,避免阻塞当前线程,导致程序无响应 + if(printLog) { + HttpPrintUtils.getInstance().printLog(logArrays, true);//线程安全方法,需在新线程执行,避免阻塞当前线程,导致程序无响应 + } } }.start(); + } catch (JSONException e) { + if(response == null){ + response = chain.proceed(request); + } + e.printStackTrace(); } catch (Exception e) { logArrays.add("<-- response url:" + URLDecoder.decode(request.url().toString(), "UTF-8")); NetWorkCost netWorkCost = NetWorkListenear.workCostMap.get(hashCode); - String cost = String.format("dns:%s,secure:%s,connect:%s,requestH:%s,requestB:%s,responseH:%s,responseB:%s", convertTimes(netWorkCost.dns) ,convertTimes(netWorkCost.secure) , convertTimes(netWorkCost.connect),convertTimes(netWorkCost.requestHeader),convertTimes(netWorkCost.requestBody) ,convertTimes(netWorkCost.resposeHeader),convertTimes(netWorkCost.resposeBody) ); - logArrays.add("<-- costtimes : "+convertTimes(netWorkCost.total)+" (" +cost + ')'); + if (netWorkCost != null) { + netWorkCost.total = new Date().getTime() - netWorkCost.total; + logArrays.add("<-- costtimes : " + netWorkCost); + } NetWorkListenear.workCostMap.remove(hashCode); logArrays.add("<-- response failed " + e.getLocalizedMessage()); logArrays.add("<-- " + e.toString()); new Thread(){ @Override public void run() { - HttpPrintUtils.getInstance().printLog(logArrays, false);//线程安全方法,需在新线程执行,避免阻塞当前线程,导致程序无响应 + if(printLog) { + HttpPrintUtils.getInstance().printLog(logArrays, false);//线程安全方法,需在新线程执行,避免阻塞当前线程,导致程序无响应 + } } }.start(); throw e;//抛出异常,用于请求接收信息 @@ -86,7 +112,7 @@ return response; } - private ArrayList<String> getRequestLog(Request request) throws IOException { + private ArrayList<String> getRequestLog(Request request) throws IOException, JSONException { RequestBody requestBody = request.body(); ArrayList<String> logArrays = new ArrayList<>(); String requestStartMessage = "--> " + request.method() + ' ' + URLDecoder.decode(request.url().toString() ,"UTF-8")+ ' ' ; @@ -120,22 +146,28 @@ String str=buffer1.readString(charset).replaceAll("%(?![0-9a-fA-F]{2})","%25"); param.put(part.headers().get(part.headers().name(0)),URLDecoder.decode(str, "UTF-8")); } - logArrays.add(GsonUtils.retractJson(new JSONObject(param).toString())); + logArrays.add(new JSONObject(param).toString(4)); }else if(requestBody instanceof FormBody){ logArrays.add("---------->REQUEST BODY[FormBody]<----------"); FormBody body = (FormBody) requestBody; for(int i = 0 ; i < body.size() ; i ++ ){ param.put(body.name(i),body.value(i)); } - logArrays.add(GsonUtils.retractJson(new JSONObject(param).toString())); + logArrays.add(new JSONObject(param).toString(4)); }else{ Buffer buffer = new Buffer(); requestBody.writeTo(buffer); logArrays.add("---------->REQUEST BODY<----------"); String str = buffer.readString(charset); try{ - logArrays.add(GsonUtils.retractJson(URLDecoder.decode(str, "UTF-8"))); - }catch (Exception e){ + str = URLDecoder.decode(str, "UTF-8"); + }catch (Exception e){} + + if(str.indexOf("[") == 0){ + logArrays.add(new JSONArray(str).toString(4)); + }else if(str.indexOf("{") == 0){ + logArrays.add(new JSONObject(str).toString(4)); + }else{ logArrays.add(str); } } @@ -147,7 +179,7 @@ } - private ArrayList<String> getResponseLog(Response response) throws IOException { + private ArrayList<String> getResponseLog(Response response) throws IOException, JSONException { ArrayList<String> logArrays = new ArrayList<>(); ResponseBody responseBody = response.body(); long contentLength = responseBody.contentLength(); @@ -173,7 +205,7 @@ if (isPlaintext(buffer)) { logArrays.add("---------->RESPONSE BODY<----------"); if (contentLength != 0) { - logArrays.add(retractJson(buffer.clone().readString(charset))); + logArrays.add(new JSONObject(buffer.clone().readString((charset))).toString(4)); } logArrays.add("<-- END HTTP (" + buffer.size() + "-byte body)"); @@ -183,57 +215,6 @@ return logArrays; } - /** - * 字符串缩进 - * @param json - * @return - */ - private String retractJson(String json){ - int level = 0 ; - StringBuffer jsonForMatStr = new StringBuffer(); - for(int index=0;index<json.length();index++)//将字符串中的字符逐个按行输出 - { - //获取s中的每个字符 - char c = json.charAt(index); - // System.out.println(s.charAt(index)); - - //level大于0并且jsonForMatStr中的最后一个字符为\n,jsonForMatStr加入\t - if (level > 0 && '\n' == jsonForMatStr.charAt(jsonForMatStr.length() - 1)) { - jsonForMatStr.append(getLevelStr(level)); - // System.out.println("123"+jsonForMatStr); - } - //遇到"{"和"["要增加空格和换行,遇到"}"和"]"要减少空格,以对应,遇到","要换行 - switch (c) { - case '{': - case '[': - jsonForMatStr.append(c + "\n"); - level++; - break; - case ',': - jsonForMatStr.append(c + "\n"); - break; - case '}': - case ']': - jsonForMatStr.append("\n"); - level--; - jsonForMatStr.append(getLevelStr(level)); - jsonForMatStr.append(c); - break; - default: - jsonForMatStr.append(c); - break; - } - } - return jsonForMatStr.toString(); - } - - private String getLevelStr(int level) { - StringBuffer levelStr = new StringBuffer(); - for (int levelI = 0; levelI < level; levelI++) { - levelStr.append("\t");//\t或空格 - } - return levelStr.toString(); - } /** * Returns true if the body in question probably contains human readable text. Uses a small sample @@ -263,18 +244,4 @@ String contentEncoding = headers.get("Content-Encoding"); return contentEncoding != null && !contentEncoding.equalsIgnoreCase("identity"); } - - private String convertTimes(long ms){ - String m = null,s=null; - final int utilS = 1000; - final int utilM = utilS*60; - if(ms/utilM>0){ - m = ms/utilM+"m"; - } - if(ms%utilM/utilS>0){ - s = ms%utilM/utilS+"s"; - } - return (m!=null?m:"")+(s!=null?s:"")+ms%utilS+"ms"; - } - } diff --git a/app/src/main/java/com/runt/open/mvvm/retrofit/api/CommonApiCenter.java b/app/src/main/java/com/runt/open/mvvm/retrofit/api/CommonApiCenter.java index fef1d1e..5376e58 100644 --- a/app/src/main/java/com/runt/open/mvvm/retrofit/api/CommonApiCenter.java +++ b/app/src/main/java/com/runt/open/mvvm/retrofit/api/CommonApiCenter.java @@ -1,17 +1,21 @@ package com.runt.open.mvvm.retrofit.api; - import com.runt.open.mvvm.data.ApkUpGradeResult; import java.util.Map; import io.reactivex.Observable; +import okhttp3.MultipartBody; +import okhttp3.ResponseBody; +import retrofit2.Call; import retrofit2.http.Field; import retrofit2.http.FieldMap; import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; +import retrofit2.http.Multipart; import retrofit2.http.POST; +import retrofit2.http.Part; import retrofit2.http.Query; import retrofit2.http.QueryMap; import retrofit2.http.Url; @@ -62,5 +66,10 @@ @GET("system/appupgrade/tourist/get/2") Observable<ApkUpGradeResult> getAppUpdate(); + @POST("updateName") + Observable<ApkUpGradeResult> updateName(@Field("username") String name); + @Multipart + @POST("updatehead") + Call<ResponseBody> updateHead(@Part MultipartBody.Part file); } diff --git a/app/src/main/java/com/runt/open/mvvm/retrofit/converter/DecryptGsonResponseBodyConverter.java b/app/src/main/java/com/runt/open/mvvm/retrofit/converter/DecryptGsonResponseBodyConverter.java index 4213ddc..befdc29 100644 --- a/app/src/main/java/com/runt/open/mvvm/retrofit/converter/DecryptGsonResponseBodyConverter.java +++ b/app/src/main/java/com/runt/open/mvvm/retrofit/converter/DecryptGsonResponseBodyConverter.java @@ -2,7 +2,7 @@ import android.util.Log; -import com.runt.open.mvvm.data.BaseApiResult; +import com.runt.open.mvvm.data.HttpApiResult; import com.runt.open.mvvm.util.GsonUtils; import com.google.gson.Gson; import com.google.gson.JsonIOException; @@ -51,13 +51,13 @@ response = decryptJsonStr(val);//解密 } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { e.printStackTrace(); - BaseApiResult apiResult = new BaseApiResult<>(); + HttpApiResult apiResult = new HttpApiResult<>(); apiResult.code = 412; apiResult.msg = "解密数据出错"+e.getMessage(); response = new Gson().toJson(apiResult); } catch (JSONException e) { e.printStackTrace(); - BaseApiResult apiResult = new BaseApiResult<>(); + HttpApiResult apiResult = new HttpApiResult<>(); apiResult.code = 414; apiResult.msg = "非标准json"; response = new Gson().toJson(apiResult); diff --git a/app/src/main/java/com/runt/open/mvvm/retrofit/net/NetWorkCost.java b/app/src/main/java/com/runt/open/mvvm/retrofit/net/NetWorkCost.java index afc660a..7131f87 100644 --- a/app/src/main/java/com/runt/open/mvvm/retrofit/net/NetWorkCost.java +++ b/app/src/main/java/com/runt/open/mvvm/retrofit/net/NetWorkCost.java @@ -11,4 +11,31 @@ //网络消耗时间 public long dns,connect,total,secure,requestHeader,requestBody,resposeHeader,resposeBody; + + @Override + public String toString() { + return "NetWorkCost{" + + "total=" + convertTimes(total) + + ", dns=" + convertTimes(dns) + + ", connect=" + convertTimes(connect) + + ", secure=" + convertTimes(secure) + + ", requestHeader=" + convertTimes(requestHeader) + + ", requestBody=" + convertTimes(requestBody) + + ", resposeHeader=" + convertTimes(resposeHeader) + + ", resposeBody=" + convertTimes(resposeBody) + + '}'; + } + + private String convertTimes(long ms){ + String m = null,s=null; + final int utilS = 1000; + final int utilM = utilS*60; + if(ms/utilM>0){ + m = ms/utilM+"m"; + } + if(ms%utilM/utilS>0){ + s = ms%utilM/utilS+"s"; + } + return (m!=null?m:"")+(s!=null?s:"")+ms%utilS+"ms"; + } } diff --git a/app/src/main/java/com/runt/open/mvvm/retrofit/net/NetWorkListenear.java b/app/src/main/java/com/runt/open/mvvm/retrofit/net/NetWorkListenear.java index 6f49237..0d824a6 100644 --- a/app/src/main/java/com/runt/open/mvvm/retrofit/net/NetWorkListenear.java +++ b/app/src/main/java/com/runt/open/mvvm/retrofit/net/NetWorkListenear.java @@ -27,13 +27,14 @@ * @purpose Created by Runt (qingingrunt2010@qq.com) on 2021-7-9. */ + public class NetWorkListenear extends EventListener { private static final String TAG = "NetworkEventListener"; final Charset UTF8 = Charset.forName("UTF-8"); public static Map<Integer, NetWorkCost> workCostMap = new HashMap<>(); - public static Factory get(){ + public static Factory get() { Factory factory = new Factory() { @NotNull @Override @@ -47,11 +48,11 @@ @Override public void callStart(@NotNull Call call) { super.callStart(call); - //mRequestId = mNextRequestId.getAndIncrement() + ""; //getAndAdd,在多线程下使用cas保证原子性 + //Log.d(TAG, "callStart hashcode:"+call.request().hashCode()); NetWorkCost netWorkCost = new NetWorkCost(); netWorkCost.total = new Date().getTime(); - workCostMap.put(call.request().hashCode(),netWorkCost); + workCostMap.put(call.request().hashCode(), netWorkCost); } @Override @@ -65,7 +66,7 @@ public void dnsEnd(@NotNull Call call, @NotNull String domainName, @NotNull List<InetAddress> inetAddressList) { super.dnsEnd(call, domainName, inetAddressList); //Log.d(TAG, "dnsEnd"); - workCostMap.get(call.request().hashCode()).dns = new Date().getTime() - workCostMap.get(call.request().hashCode()).dns; + workCostMap.get(call.request().hashCode()).dns = new Date().getTime() - workCostMap.get(call.request().hashCode()).dns; } @Override @@ -100,9 +101,10 @@ @Override public void connectFailed(@NotNull Call call, @NotNull InetSocketAddress inetSocketAddress, @NotNull Proxy proxy, @Nullable Protocol protocol, @NotNull IOException ioe) { super.connectFailed(call, inetSocketAddress, proxy, protocol, ioe); - workCostMap.get(call.request().hashCode()).connect = new Date().getTime() - workCostMap.get(call.request().hashCode()).connect; - workCostMap.get(call.request().hashCode()).total = new Date().getTime() - workCostMap.get(call.request().hashCode()).total; - //Log.d(TAG, "connectFailed"); + NetWorkCost workCost = workCostMap.get(call.request().hashCode()); + workCost.connect = new Date().getTime() - workCost.connect; + workCost.total = new Date().getTime() - workCost.total; + //Log.d(TAG, "connectFailed hashcode:"+call.request().hashCode() +" "+workCost); } @Override @@ -158,16 +160,20 @@ public void responseBodyEnd(@NotNull Call call, long byteCount) { super.responseBodyEnd(call, byteCount); //Log.d(TAG, "responseBodyEnd"); - workCostMap.get(call.request().hashCode()).resposeBody = new Date().getTime() - workCostMap.get(call.request().hashCode()).resposeBody; - workCostMap.get(call.request().hashCode()).total = new Date().getTime() - workCostMap.get(call.request().hashCode()).total; + NetWorkCost workCost = workCostMap.get(call.request().hashCode()); + workCost.resposeBody = new Date().getTime() - workCost.resposeBody; + workCost.total = new Date().getTime() - workCost.total; } @Override public void callFailed(@NotNull Call call, @NotNull IOException ioe) { super.callFailed(call, ioe); - workCostMap.get(call.request().hashCode()).total = new Date().getTime() - workCostMap.get(call.request().hashCode()).total; - //Log.d(TAG, "callFailed"); + NetWorkCost workCost = workCostMap.get(call.request().hashCode()); + if (workCost != null) { + workCost.total = new Date().getTime() - workCost.total; + } + //Log.d(TAG, "callFailed hashcode:"+call.request().hashCode() +" "+workCost); } } diff --git a/app/src/main/java/com/runt/open/mvvm/retrofit/observable/HttpObserver.java b/app/src/main/java/com/runt/open/mvvm/retrofit/observable/HttpObserver.java index 3a4ac2c..a99f74e 100644 --- a/app/src/main/java/com/runt/open/mvvm/retrofit/observable/HttpObserver.java +++ b/app/src/main/java/com/runt/open/mvvm/retrofit/observable/HttpObserver.java @@ -1,96 +1,71 @@ package com.runt.open.mvvm.retrofit.observable; -import android.accounts.NetworkErrorException; import android.util.Log; -import androidx.annotation.NonNull; -import androidx.lifecycle.MutableLiveData; +import com.google.gson.Gson; +import com.runt.open.mvvm.data.HttpApiResult; - -import com.runt.open.mvvm.data.BaseApiResult; - -import java.io.IOException; -import java.lang.reflect.ParameterizedType; +import java.net.ConnectException; import java.net.SocketTimeoutException; +import java.net.UnknownHostException; +import java.util.concurrent.TimeoutException; +import java.util.regex.Pattern; -import io.reactivex.SingleObserver; -import io.reactivex.observers.DisposableObserver; -import retrofit2.Response; +import io.reactivex.Observer; +import io.reactivex.disposables.Disposable; +import retrofit2.adapter.rxjava2.HttpException; /** * 网络请求观察 * Created by Administrator on 2021/11/11 0011. */ -public abstract class HttpObserver<M extends BaseApiResult> extends DisposableObserver<Response<M>> implements SingleObserver<Response<M>> { +public abstract class HttpObserver<RESULT> implements Observer<HttpApiResult<RESULT>> { final String TAG = "HttpObserver"; - MutableLiveData<M> resultLive; - - public HttpObserver(MutableLiveData<M> resultLive) { - this.resultLive = resultLive; - } - - @Override - public void onNext(Response<M> response) { - onExcuted(response); + public void onSubscribe(Disposable d) { + Log.d(TAG,"onSubscribe "+hashCode()); } @Override - public void onError(Throwable throwable) { - Log.i("subscribe","onError"); - - try { - Log.e(TAG,this.getClass().getSimpleName()+" mes:"+throwable.getMessage()); - Class<M> entityClass = (Class<M>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]; - M t = entityClass.newInstance();//实例化一个泛型 - t.code = 410; - if( throwable instanceof SocketTimeoutException){ - t.msg = "服务请求超时,请稍候再试";//设置错误信息 - }else if( throwable instanceof NetworkErrorException){ - t.msg = "网络连接不畅,请检查您的网络设置";//设置错误信息 - }else{ - t.msg = throwable.getMessage();//设置错误信息 - } - resultLive.setValue(t); - } catch (ClassCastException e) { - e.printStackTrace(); - M t = (M) new BaseApiResult<String>(); - t.code = 409; - t.msg = "实例化对象未指定泛型实体类"; - resultLive.setValue(t); - } catch (Exception e) { - e.printStackTrace(); - M t = (M) new BaseApiResult<String>(); - t.code = 409; - t.msg = e.getMessage(); - resultLive.setValue(t); - } - } - - @Override - public void onSuccess(Response<M> response) { - onExcuted(response); - } - - private void onExcuted(@NonNull Response<M> response){ - - if(response.body() != null){ - resultLive.setValue(response.body()); + public void onNext(HttpApiResult<RESULT> httpResult) { + Log.d(TAG,"onNext "+httpResult); + if (httpResult != null && httpResult.code == 0) { + onSuccess(httpResult.data); }else{ - try { - String error = response.errorBody().string(); - Log.i("subscribe","onExcuted "+error); - onError(new Throwable(error)); - } catch (IOException e) { - e.printStackTrace(); - } + onFailed(httpResult);//接口返回错误 } } + + @Override + public void onError(Throwable e) { + e.printStackTrace(); + Log.e(TAG,"onError "+e.getMessage()+" "+hashCode()); + int code = 600; + String msg = "网络请求失败,请检查网络或稍后重试"; + if( e instanceof ConnectException || e instanceof TimeoutException + || e instanceof SocketTimeoutException || e instanceof UnknownHostException){ + code = 601; + msg = "网络请求失败,请检查网络或稍后重试"; + }else if( e instanceof HttpException){ + String regEx = "[^0-9]"; + Log.i(TAG,"code:"+ Pattern.compile(regEx).matcher(e.getMessage()).replaceAll("")); + String error = Pattern.compile(regEx).matcher(e.getMessage()).replaceAll(""); + code = error.length()>0?Integer.parseInt(error):500; + msg = error.length()>0?"服务器请求失败":"登录信息验证失败"; + } + HttpApiResult httpResult = new Gson().fromJson("{'code':"+code+",'msg':'"+msg+"'}", HttpApiResult.class); + onFailed(httpResult); + } + @Override public void onComplete() { - Log.i("subscribe","onComplete"); + Log.i(TAG,"onComplete "+hashCode()); } + protected abstract void onSuccess(RESULT data); + + protected void onFailed(HttpApiResult httpResult){} + } diff --git a/app/src/main/java/com/runt/open/mvvm/retrofit/utils/HttpPrintUtils.java b/app/src/main/java/com/runt/open/mvvm/retrofit/utils/HttpPrintUtils.java index 53dd3b0..7743709 100644 --- a/app/src/main/java/com/runt/open/mvvm/retrofit/utils/HttpPrintUtils.java +++ b/app/src/main/java/com/runt/open/mvvm/retrofit/utils/HttpPrintUtils.java @@ -1,26 +1,20 @@ package com.runt.open.mvvm.retrofit.utils; -import com.runt.open.mvvm.BuildConfig; -import com.runt.open.mvvm.util.GsonUtils; -import com.runt.open.mvvm.util.MyLog; +import android.util.Log; -import java.io.EOFException; import java.util.ArrayList; - -import okio.Buffer; /** * My father is Object, ites purpose of 单例模式 保证synchronized方法的线程安全性 * * @purpose Created by Runt (qingingrunt2010@qq.com) on 2021-5-13. */ - public class HttpPrintUtils { String TAG = "HttpPrintUtils"; static HttpPrintUtils instance; public static HttpPrintUtils getInstance(){ if(instance == null){ - instance = new HttpPrintUtils(); + instance = new HttpPrintUtils(); } return instance; } @@ -76,14 +70,12 @@ logArrays.add("┗"+getEmptyStr((length-end.length())/2,"━")+end+getEmptyStr((length-end.length())/2,"━")+"┛\n"); logArrays.add(" \n\n\n"); //Logger.DEFAULT.log(sb.toString());//打印log,避免多个log语句,导致log输出时其他线程的log输出切入此输出阵列内 - if(BuildConfig.DEBUG) { - for(int i = 0 ; i < logArrays.size() ; i ++ ){ - String str = logArrays.get(i); - if (info) { - MyLog.i(TAG , str.replace("\n","")+" "+logArrays.size()+" "+i); - } else { - MyLog.e(TAG , str.replace("\n","")+" "+logArrays.size()+" "+i); - } + for(int i = 0 ; i < logArrays.size() ; i ++ ){ + String str = logArrays.get(i); + if (info) { + Log.i(TAG , str.replace("\n","")+" "+logArrays.size()+" "+i); + } else { + Log.e(TAG , str.replace("\n","")+" "+logArrays.size()+" "+i); } } } @@ -102,16 +94,12 @@ s = s.substring(0,totalLength*3)+"..."; } s = s.replace("\t"," ");//缩进替换空格 - if(s.indexOf("\":{\"")>-1 || s.indexOf("\":[{\"")>-1 || s.indexOf("\":[[")>-1){//内容非校正缩进,且为json字符规范 - splitStr(s.substring(0,s.indexOf("\":")+2)+ GsonUtils.retractJson(s.substring(s.indexOf("\":")+2)),totalLength,list); + if(s.length()> totalLength){ + outOflength(s,totalLength,list); }else { - if(s.length()> totalLength){ - outOflength(s,totalLength,list); - }else { - logStr = "┃ " + s + getEmptyStr((totalLength - 16 - s.length()), " "); - //处理中文间距,保证打印无偏差 - list.add(logStr + getEmptyStr((totalLength - logStr.length() - 1 - hasCNchar(logStr)), " ") + "┃ "/*+logStr.length()+" "+logStr.getBytes().length+" "+(" ").getBytes().length +" "+hasCNchar(s)*/ + "\n"); - } + logStr = "┃ " + s + getEmptyStr((totalLength - 16 - s.length()), " "); + //处理中文间距,保证打印无偏差 + list.add(logStr + getEmptyStr((totalLength - logStr.length() - 1 - hasCNchar(logStr)), " ") + "┃ "/*+logStr.length()+" "+logStr.getBytes().length+" "+(" ").getBytes().length +" "+hasCNchar(s)*/ + "\n"); } } } @@ -182,29 +170,6 @@ sb.append(space); } return sb.toString(); - } - /** - * Returns true if the body in question probably contains human readable text. Uses a small sample - * of code points to detect unicode control characters commonly used in binary file signatures. - */ - static boolean isPlaintext(Buffer buffer) { - try { - Buffer prefix = new Buffer(); - long byteCount = buffer.size() < 64 ? buffer.size() : 64; - buffer.copyTo(prefix, 0, byteCount); - for (int i = 0; i < 16; i++) { - if (prefix.exhausted()) { - break; - } - int codePoint = prefix.readUtf8CodePoint(); - if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) { - return false; - } - } - return true; - } catch (EOFException e) { - return false; // Truncated UTF-8 sequence. - } } } diff --git a/app/src/main/java/com/runt/open/mvvm/retrofit/utils/RetrofitUtils.java b/app/src/main/java/com/runt/open/mvvm/retrofit/utils/RetrofitUtils.java index df2ae38..134853b 100644 --- a/app/src/main/java/com/runt/open/mvvm/retrofit/utils/RetrofitUtils.java +++ b/app/src/main/java/com/runt/open/mvvm/retrofit/utils/RetrofitUtils.java @@ -23,7 +23,6 @@ */ public class RetrofitUtils { - public static String HOST_IP_ADDR; static RetrofitUtils instance; Retrofit retrofit/*log输出,驼峰转换*/,unHumpRetrofit/*log输出,不强制驼峰转换*/, unLogRetrofit/*log不输出,驼峰转换*/,unLogHumpRetorfit/*log不输出,不强制驼峰转换*/; @@ -108,7 +107,7 @@ //设置OKHttpClient .client(client) //设置baseUrl,注意,baseUrl必须后缀"/" - .baseUrl(BuildConfig.ENVIRONMENT.equals("develop")?HOST_IP_ADDR:BuildConfig.HOST_IP_ADDR) + .baseUrl(BuildConfig.HOST_IP_ADDR+"api/v1/") .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); } diff --git a/app/src/main/java/com/runt/open/mvvm/ui/login/LoginViewModel.java b/app/src/main/java/com/runt/open/mvvm/ui/login/LoginViewModel.java index eda4bd3..b83f332 100644 --- a/app/src/main/java/com/runt/open/mvvm/ui/login/LoginViewModel.java +++ b/app/src/main/java/com/runt/open/mvvm/ui/login/LoginViewModel.java @@ -29,7 +29,12 @@ MutableLiveData<Results.StringApiResult> verifyResult = new MutableLiveData<>(); MutableLiveData<Results.StringApiResult> resetResult = new MutableLiveData<>(); MutableLiveData<Results.StringApiResult> registerResult = new MutableLiveData<>(); - + HttpObserver<Results.LoggedInUser> logginObserver = new HttpObserver<Results.LoggedInUser>(){ + @Override + protected void onSuccess(Results.LoggedInUser data) { + loginResult.setValue(data); + } + }; public MutableLiveData<Results.LoggedInUser> getLoginResult() { return loginResult; } @@ -46,7 +51,7 @@ public void login(String username, String password) { // can be launched in a separate asynchronous job final Observable<Results.LoggedInUser> userObservable = loginApi.login(username, password); - httpObserverOnLoading(userObservable,new HttpObserver<Results.LoggedInUser>(loginResult){}); + httpObserverOnLoading(userObservable,logginObserver); } /** @@ -55,8 +60,7 @@ * @param code */ public void loginByCode(String phone,String code){ - httpObserverOnLoading(loginApi.loginByCode(phone,code), - new HttpObserver<Results.LoggedInUser>(loginResult){}); + httpObserverOnLoading(loginApi.loginByCode(phone,code),logginObserver); } /** @@ -66,7 +70,7 @@ * @param pass */ public void resetPwd(String phone,String sms,String pass){ - httpObserverOnLoading(loginApi.resetLoginPwd(phone, sms, pass), new HttpObserver<Results.StringApiResult>(resetResult) {}); + httpObserverOnLoading(loginApi.resetLoginPwd(phone, sms, pass),logginObserver); } /** @@ -76,7 +80,12 @@ * @param pass */ public void register(String phone,String sms,String pass){ - httpObserverOnLoading(loginApi.register(phone, sms, pass), new HttpObserver<Results.StringApiResult>(resetResult) {}); + httpObserverOnLoading(loginApi.register(phone, sms, pass), new HttpObserver<Results.StringApiResult>(){ + @Override + protected void onSuccess(Results.StringApiResult data) { + resetResult.setValue(data); + } + }); } /** @@ -110,7 +119,12 @@ */ public void getVerifyCode(String url,String phone){ String time = new Date().getTime()+""; - httpObserverOnLoading(loginApi.getVerifyCode(url, phone, randomString(phone, time), time), new HttpObserver<Results.StringApiResult>(verifyResult){}); + httpObserverOnLoading(loginApi.getVerifyCode(url, phone, randomString(phone, time), time), new HttpObserver<Results.StringApiResult>(){ + @Override + protected void onSuccess(Results.StringApiResult data) { + verifyResult.setValue(data); + } + }); } /** diff --git a/app/src/main/java/com/runt/open/mvvm/ui/login/RegisterLoginActivity.java b/app/src/main/java/com/runt/open/mvvm/ui/login/RegisterLoginActivity.java index ab84fd8..224b886 100644 --- a/app/src/main/java/com/runt/open/mvvm/ui/login/RegisterLoginActivity.java +++ b/app/src/main/java/com/runt/open/mvvm/ui/login/RegisterLoginActivity.java @@ -29,30 +29,23 @@ @Override public void initViews() { - binding.txtGetVerify.setOnClickListener(onclick); - binding.txtForgot.setOnClickListener(onclick); - binding.txtLogin.setOnClickListener(onclick); - binding.txtRegister.setOnClickListener(onclick); - binding.txtPrivacy.setOnClickListener(onclick); - long getTime = getLongProjectPrefrence(VERIFY_CODE); - long cha = new Date().getTime() - getTime; - if(cha <1000*60){ - CodeTimer codeTimer = new CodeTimer(cha, 1000, binding.txtGetVerify); - codeTimer.startUp(); - } - changeView(); - binding.editPhone.setText(getStringProjectPrefrence(Configuration.KEY_USERNAME)); - viewModel.getVerifyResult().observe(this, stringApiResult -> { + mBinding.txtGetVerify.setOnClickListener(onclick); + mBinding.txtForgot.setOnClickListener(onclick); + mBinding.txtLogin.setOnClickListener(onclick); + mBinding.txtRegister.setOnClickListener(onclick); + mBinding.txtPrivacy.setOnClickListener(onclick); + mBinding.editPhone.setText(getStringProjectPrefrence(Configuration.KEY_USERNAME)); + mViewModel.getVerifyResult().observe(this, stringApiResult -> { if(stringApiResult.code == 200){ }else{ showToast(stringApiResult.msg); } }); - viewModel.getLoginResult().observe(this,loggedInUser -> { + mViewModel.getLoginResult().observe(this, loggedInUser -> { if(loggedInUser.code == 200){ putBooleanProjectPrefrence(Configuration.IS_LOGIN,true); - putStringProjectPrefrence(Configuration.KEY_USERNAME,binding.editPhone.getText().toString()); + putStringProjectPrefrence(Configuration.KEY_USERNAME, mBinding.editPhone.getText().toString()); UserBean user = new Gson().fromJson(new Gson().toJson(loggedInUser.data) ,UserBean.class); UserBean.setUser(user); @@ -67,6 +60,17 @@ }); } + @Override + public void loadData() { + long getTime = getLongProjectPrefrence(VERIFY_CODE); + long cha = new Date().getTime() - getTime; + if(cha <1000*60){ + CodeTimer codeTimer = new CodeTimer(cha, 1000, mBinding.txtGetVerify); + codeTimer.startUp(); + } + changeView(); + } + CustomClickListener onclick = new CustomClickListener() { @Override protected void onSingleClick(View view) { @@ -76,16 +80,16 @@ break; case R.id.txt_get_verify: - String phone = binding.editPhone.getText().toString(); + String phone = mBinding.editPhone.getText().toString(); if(!verifyPhone(phone)){//验证手机 return; } if(type==2){//获取注册验证码 - viewModel.getRegisterSMS(phone); + mViewModel.getRegisterSMS(phone); }else if(type ==1){ - viewModel.getForgetSMS( phone); + mViewModel.getForgetSMS( phone); }else if(type == -1){ - viewModel.getLoginSMS( phone); + mViewModel.getLoginSMS( phone); } break; case R.id.txt_privacy: @@ -116,53 +120,53 @@ * 修改页面布局 */ private void changeView(){ - binding.button.setEnabled(true); - binding.txtRegister.setVisibility(View.VISIBLE); - binding.checkbox.setVisibility(View.GONE); - binding.txtPrivacy.setVisibility(View.GONE); + mBinding.button.setEnabled(true); + mBinding.txtRegister.setVisibility(View.VISIBLE); + mBinding.checkbox.setVisibility(View.GONE); + mBinding.txtPrivacy.setVisibility(View.GONE); switch (type){ case -1://短信登录 - binding.editVerifyCode.setVisibility(View.VISIBLE); - binding.txtGetVerify.setVisibility(View.VISIBLE); - binding.editPass.setVisibility(View.GONE); - binding.editPassRepeat.setVisibility(View.GONE); - binding.txtForgot.setVisibility(View.VISIBLE); - binding.txtLogin.setText(getResources().getString(R.string.login)); - binding.button.setText(getResources().getString(R.string.login)); - binding.checkbox.setVisibility(View.VISIBLE); - binding.txtPrivacy.setVisibility(View.VISIBLE); + mBinding.editVerifyCode.setVisibility(View.VISIBLE); + mBinding.txtGetVerify.setVisibility(View.VISIBLE); + mBinding.editPass.setVisibility(View.GONE); + mBinding.editPassRepeat.setVisibility(View.GONE); + mBinding.txtForgot.setVisibility(View.VISIBLE); + mBinding.txtLogin.setText(getResources().getString(R.string.login)); + mBinding.button.setText(getResources().getString(R.string.login)); + mBinding.checkbox.setVisibility(View.VISIBLE); + mBinding.txtPrivacy.setVisibility(View.VISIBLE); break; case 0://登录 - binding.editVerifyCode.setVisibility(View.GONE); - binding.txtGetVerify.setVisibility(View.GONE); - binding.editPass.setVisibility(View.VISIBLE); - binding.editPassRepeat.setVisibility(View.GONE); - binding.txtForgot.setVisibility(View.VISIBLE); - binding.txtLogin.setText(getResources().getString(R.string.msg_login)); - binding.button.setText(getResources().getString(R.string.login)); + mBinding.editVerifyCode.setVisibility(View.GONE); + mBinding.txtGetVerify.setVisibility(View.GONE); + mBinding.editPass.setVisibility(View.VISIBLE); + mBinding.editPassRepeat.setVisibility(View.GONE); + mBinding.txtForgot.setVisibility(View.VISIBLE); + mBinding.txtLogin.setText(getResources().getString(R.string.msg_login)); + mBinding.button.setText(getResources().getString(R.string.login)); break; case 1://忘记密码 - binding.txtForgot.setVisibility(View.INVISIBLE); - binding.editVerifyCode.setVisibility(View.VISIBLE); - binding.txtGetVerify.setVisibility(View.VISIBLE); - binding.editPass.setVisibility(View.VISIBLE); - binding.editPassRepeat.setVisibility(View.VISIBLE); - binding.txtLogin.setText(getResources().getString(R.string.login)); - binding.button.setText(getResources().getString(R.string.str_confirm)); + mBinding.txtForgot.setVisibility(View.INVISIBLE); + mBinding.editVerifyCode.setVisibility(View.VISIBLE); + mBinding.txtGetVerify.setVisibility(View.VISIBLE); + mBinding.editPass.setVisibility(View.VISIBLE); + mBinding.editPassRepeat.setVisibility(View.VISIBLE); + mBinding.txtLogin.setText(getResources().getString(R.string.login)); + mBinding.button.setText(getResources().getString(R.string.str_confirm)); break; case 2://注册 - binding.checkbox.setVisibility(View.VISIBLE); - binding.txtPrivacy.setVisibility(View.VISIBLE); - binding.txtRegister.setVisibility(View.INVISIBLE); - binding.editVerifyCode.setVisibility(View.VISIBLE); - binding.txtGetVerify.setVisibility(View.VISIBLE); - binding.editPass.setVisibility(View.VISIBLE); - binding.editPassRepeat.setVisibility(View.VISIBLE); - binding.txtLogin.setText(getResources().getString(R.string.login)); - binding.button.setText(getResources().getString(R.string.register)); + mBinding.checkbox.setVisibility(View.VISIBLE); + mBinding.txtPrivacy.setVisibility(View.VISIBLE); + mBinding.txtRegister.setVisibility(View.INVISIBLE); + mBinding.editVerifyCode.setVisibility(View.VISIBLE); + mBinding.txtGetVerify.setVisibility(View.VISIBLE); + mBinding.editPass.setVisibility(View.VISIBLE); + mBinding.editPassRepeat.setVisibility(View.VISIBLE); + mBinding.txtLogin.setText(getResources().getString(R.string.login)); + mBinding.button.setText(getResources().getString(R.string.register)); break; } - clearText(binding.editPassRepeat,binding.editPass,binding.editPhone,binding.editVerifyCode); + clearText(mBinding.editPassRepeat, mBinding.editPass, mBinding.editPhone, mBinding.editVerifyCode); } private void clearText(EditText... editTextes){ @@ -178,10 +182,10 @@ * 提交数据 */ public void submit(){ - String phone = binding.editPhone.getText().toString(); - String pass = binding.editPass .getText().toString(); - String veriCode = binding.editVerifyCode.getText().toString(); - String invite = binding.editPassRepeat.getText().toString(); + String phone = mBinding.editPhone.getText().toString(); + String pass = mBinding.editPass .getText().toString(); + String veriCode = mBinding.editVerifyCode.getText().toString(); + String invite = mBinding.editPassRepeat.getText().toString(); if(!verifyPhone(phone)){//验证手机 return; } @@ -191,17 +195,17 @@ showToast(R.string.input_verify_code); return; } - if(!binding.checkbox.isChecked()){ + if(!mBinding.checkbox.isChecked()){ showToast("请阅读并勾选《隐私条款》"); return; } - viewModel.loginByCode(phone,veriCode); + mViewModel.loginByCode(phone,veriCode); break; case 0: if(!verifyPassWord(pass)){//验证密码 return; } - viewModel.login(phone,pass); + mViewModel.login(phone,pass); break; case 1: if(!verifyPassWord(pass)){//验证密码 @@ -220,7 +224,7 @@ showToast(R.string.str_new_verify_failed); return; } - viewModel.resetPwd(phone,veriCode,pass); + mViewModel.resetPwd(phone,veriCode,pass); break; case 2://注册 if(!verifyPassWord(pass)){//验证密码 @@ -230,11 +234,11 @@ showToast(R.string.input_verify_code); return; } - if(!binding.checkbox.isChecked()){ + if(!mBinding.checkbox.isChecked()){ showToast("请阅读并勾选《隐私条款》"); return; } - viewModel.register(phone,veriCode,pass); + mViewModel.register(phone,veriCode,pass); break; } } diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/MainActivity.java b/app/src/main/java/com/runt/open/mvvm/ui/main/MainActivity.java new file mode 100644 index 0000000..090cfa4 --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/ui/main/MainActivity.java @@ -0,0 +1,153 @@ +package com.runt.open.mvvm.ui.main; + +import android.Manifest; +import android.content.Intent; +import android.content.res.ColorStateList; +import android.view.KeyEvent; +import android.view.View; + +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; +import androidx.viewpager2.widget.ViewPager2; + +import com.google.android.material.bottomnavigation.BottomNavigationView; +import com.permissionx.guolindev.PermissionX; +import com.runt.open.mvvm.R; +import com.runt.open.mvvm.base.activities.BaseActivity; +import com.runt.open.mvvm.base.adapter.FragmentAdapter; +import com.runt.open.mvvm.base.fragments.BaseFragment; +import com.runt.open.mvvm.data.PhoneDevice; +import com.runt.open.mvvm.databinding.ActivityMainBinding; +import com.runt.open.mvvm.listener.CustomClickListener; +import com.runt.open.mvvm.listener.ResPonse; +import com.runt.open.mvvm.ui.login.RegisterLoginActivity; +import com.runt.open.mvvm.ui.login.UserBean; +import com.runt.open.mvvm.ui.main.home.HomeFragment; +import com.runt.open.mvvm.ui.main.mine.MineFragment; +import com.runt.open.mvvm.ui.main.service.ServiceFragment; + +import java.util.Arrays; + +public class MainActivity extends BaseActivity<ActivityMainBinding, MainViewModel> { + + private BaseFragment[] fragments = {new HomeFragment(),new ServiceFragment(),new MineFragment()} ; + ActivityResultLauncher<Intent> loginLaunch = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> { + if(result.getResultCode() == RESULT_CODE_SUCESS){ + fragments[2].loadData();//登录后重新刷新 + }else if(result.getResultCode() != RESULT_CODE_SUCESS){ + mBinding.viewPager2.setCurrentItem(0); + } + }); + + @Override + public void initViews() { + + mBinding.titleBar.setRightDra(getResources().getDrawable(R.mipmap.icon_white_setting)); + mBinding.titleBar.setRightClick(new CustomClickListener() { + @Override + protected void onSingleClick(View view) { + //startActivityForResult(new Intent(mContext,SettingActivity.class),REQUEST_CODE_LOGOUT);//打开设置 + } + }); + final FragmentAdapter fragmentAdapter = new FragmentAdapter(this); + fragmentAdapter.setFragments(Arrays.asList(fragments)); + //设置当前可见Item左右可见page数,次范围内不会被销毁 + //禁用预加载 + mBinding.viewPager2.setOffscreenPageLimit(ViewPager2.OFFSCREEN_PAGE_LIMIT_DEFAULT); + mBinding.viewPager2.setAdapter(fragmentAdapter); + mBinding.viewPager2.setCurrentItem(0); + mBinding.viewPager2.setUserInputEnabled(false); //true:滑动,false:禁止滑动 + mBinding.viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + setTitleStr(position); + } + + @Override + public void onPageSelected(int position) { + mBinding.navView.getMenu().getItem(position).setChecked(true); + if(position == 2 && UserBean.getUser() == null){ + loginLaunch.launch(new Intent(mContext, RegisterLoginActivity.class)); + } + } + }); + ColorStateList csl = getResources().getColorStateList(R.color.home_nav_color); + mBinding.navView.setItemTextColor(csl);//设置文本颜色 + mBinding.navView.setItemIconTintList(csl);//图标着色 + mBinding.navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);//监听 + + } + + @Override + public void loadData() { + checkPermission(); + } + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) { + backExit(); + return true; + } + return super.onKeyDown(keyCode, event); + } + + /** + * 底部导航监听 + */ + private BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = item -> { + for(int i = 0 ; i < mBinding.navView.getMenu().size() ; i ++){ + if(item.getItemId() == mBinding.navView.getMenu().getItem(i).getItemId()){ + mBinding.viewPager2.setCurrentItem(i); + return true; + } + } + return false; + }; + + /** + * 设置标题 + * @param position + */ + private void setTitleStr(int position){ + switch (position){ + case 0: + setTitle("资讯"); + break; + case 1: + setTitle("服务"); + break; + case 2: + setTitle("个人中心"); + break; + } + } + private void showPermissionDialog(){ + + showDialog("警告", "软件需要权限才能运行", "申请权限", "退出", new ResPonse() { + @Override + public void doSuccess(Object obj) { + checkPermission(); + } + + @Override + public void doError(Object obj) { + finish(); + System.exit(0); + } + }); + } + private void checkPermission(){ + PermissionX.init(MainActivity.this) + .permissions(Manifest.permission.READ_PHONE_STATE) + .request((allGranted, grantedList, deniedList) -> { + if(allGranted){ + PhoneDevice.setDevice(mContext); + }else{ + showPermissionDialog(); + } + + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/dashboard/DashboardFragment.java b/app/src/main/java/com/runt/open/mvvm/ui/main/dashboard/DashboardFragment.java deleted file mode 100644 index 5f93e54..0000000 --- a/app/src/main/java/com/runt/open/mvvm/ui/main/dashboard/DashboardFragment.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.runt.open.mvvm.ui.main.dashboard; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProvider; - -import com.runt.open.mvvm.databinding.FragmentDashboardBinding; - -public class DashboardFragment extends Fragment { - - private DashboardViewModel dashboardViewModel; - private FragmentDashboardBinding binding; - - public View onCreateView(@NonNull LayoutInflater inflater, - ViewGroup container, Bundle savedInstanceState) { - dashboardViewModel = - new ViewModelProvider(this).get(DashboardViewModel.class); - - binding = FragmentDashboardBinding.inflate(inflater, container, false); - View root = binding.getRoot(); - - final TextView textView = binding.textDashboard; - dashboardViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() { - @Override - public void onChanged(@Nullable String s) { - textView.setText(s); - } - }); - return root; - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - binding = null; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/dashboard/DashboardViewModel.java b/app/src/main/java/com/runt/open/mvvm/ui/main/dashboard/DashboardViewModel.java deleted file mode 100644 index b2d3f43..0000000 --- a/app/src/main/java/com/runt/open/mvvm/ui/main/dashboard/DashboardViewModel.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.runt.open.mvvm.ui.main.dashboard; - -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; - -public class DashboardViewModel extends ViewModel { - - private MutableLiveData<String> mText; - - public DashboardViewModel() { - mText = new MutableLiveData<>(); - mText.setValue("This is dashboard fragment"); - } - - public LiveData<String> getText() { - return mText; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/home/HomeFragment.java b/app/src/main/java/com/runt/open/mvvm/ui/main/home/HomeFragment.java index 2a93b5b..7e944e6 100644 --- a/app/src/main/java/com/runt/open/mvvm/ui/main/home/HomeFragment.java +++ b/app/src/main/java/com/runt/open/mvvm/ui/main/home/HomeFragment.java @@ -1,33 +1,17 @@ package com.runt.open.mvvm.ui.main.home; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; +import com.runt.open.mvvm.base.fragments.LoadPageFragment; +import com.runt.open.mvvm.databinding.RefreshRecyclerBinding; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProvider; +import java.util.HashMap; +import java.util.Map; -import com.runt.open.mvvm.base.fragments.BaseFragment; -import com.runt.open.mvvm.databinding.FragmentHomeBinding; - -public class HomeFragment extends BaseFragment<FragmentHomeBinding,HomeViewModel> { - +public class HomeFragment extends LoadPageFragment<RefreshRecyclerBinding,HomeViewModel,MsgAdapter,Message> { @Override - public void initViews() { - final TextView textView = binding.textHome; - viewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() { - @Override - public void onChanged(@Nullable String s) { - textView.setText(s); - } - }); + protected Map requestParams() { + return new HashMap(); } } \ No newline at end of file diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/home/HomeViewModel.java b/app/src/main/java/com/runt/open/mvvm/ui/main/home/HomeViewModel.java index 34dbdc4..1d83123 100644 --- a/app/src/main/java/com/runt/open/mvvm/ui/main/home/HomeViewModel.java +++ b/app/src/main/java/com/runt/open/mvvm/ui/main/home/HomeViewModel.java @@ -1,19 +1,12 @@ package com.runt.open.mvvm.ui.main.home; -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; +import com.runt.open.mvvm.base.model.LoadPageViewModel; +import com.runt.open.mvvm.data.Results; -public class HomeViewModel extends ViewModel { +public class HomeViewModel extends LoadPageViewModel<Results.MessageResult> { - private MutableLiveData<String> mText; - - public HomeViewModel() { - mText = new MutableLiveData<>(); - mText.setValue("This is home fragment"); - } - - public LiveData<String> getText() { - return mText; + @Override + protected String requestUrl() { + return "getMsgList"; } } \ No newline at end of file diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/home/Message.java b/app/src/main/java/com/runt/open/mvvm/ui/main/home/Message.java new file mode 100644 index 0000000..4aede0c --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/ui/main/home/Message.java @@ -0,0 +1,8 @@ +package com.runt.open.mvvm.ui.main.home; + +/** + * @purpose Created by Runt (qingingrunt2010@qq.com) on 2022/7/27. + */ +public class Message { + public String content,cTime,title; +} diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/home/MsgAdapter.java b/app/src/main/java/com/runt/open/mvvm/ui/main/home/MsgAdapter.java new file mode 100644 index 0000000..c13fc9e --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/ui/main/home/MsgAdapter.java @@ -0,0 +1,33 @@ +package com.runt.open.mvvm.ui.main.home; + +import android.view.View; + +import com.runt.open.mvvm.base.adapter.BaseAdapter; +import com.runt.open.mvvm.databinding.ItemMsgBinding; +import com.runt.open.mvvm.listener.CustomClickListener; +import com.runt.open.mvvm.util.HandleDate; + +import java.util.Date; + +/** + * My father is Object, ites purpose of + * + * @purpose Created by Runt (qingingrunt2010@qq.com) on 2020-8-21. + */ + +public class MsgAdapter extends BaseAdapter<Message, ItemMsgBinding> { + + @Override + protected void onBindView(ItemMsgBinding binding, int position, Message message) { + binding.txtDetail.setText(message.content); + Date date = new Date(message.cTime); + binding.txtTime.setText(HandleDate.getTimeStateNew(date)); + binding.txtTitle.setText(message.title); + binding.getRoot().setOnClickListener(new CustomClickListener() { + @Override + protected void onSingleClick(View view) { + //context.startActivity(new Intent(context, MsgDetailActivity.class).putExtra("id", data.get("id").toString())); + } + }); + } +} diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/mine/MineFragment.java b/app/src/main/java/com/runt/open/mvvm/ui/main/mine/MineFragment.java new file mode 100644 index 0000000..d06e356 --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/ui/main/mine/MineFragment.java @@ -0,0 +1,177 @@ +package com.runt.open.mvvm.ui.main.mine; + +import android.app.Activity; +import android.content.Intent; +import android.view.View; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.permissionx.guolindev.PermissionX; +import com.runt.open.mvvm.BuildConfig; +import com.runt.open.mvvm.R; +import com.runt.open.mvvm.base.fragments.BaseFragment; +import com.runt.open.mvvm.databinding.FragmentMineBinding; +import com.runt.open.mvvm.listener.ResPonse; +import com.runt.open.mvvm.retrofit.observable.HttpObserver; +import com.runt.open.mvvm.ui.login.UserBean; +import com.runt.open.mvvm.util.MyLog; +import com.wildma.pictureselector.PictureSelector; + +import java.io.File; + +import okhttp3.ResponseBody; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +/** + * My father is Object, ites purpose of + * + * @purpose Created by Runt (qingingrunt2010@qq.com) on 2020-9-15. + */ + +public class MineFragment extends BaseFragment<FragmentMineBinding,MineViewModel> implements View.OnClickListener { + + private final String TAG = "MineFragment"; + + @Override + public void initViews() { + } + + @Override + public void loadData() { + if(UserBean.getUser() != null){ + RequestOptions options = new RequestOptions() + .placeholder(R.mipmap.default_head)//图片加载出来前,显示的图片 + .fallback(R.mipmap.default_head) //url为空的时候,显示的图片 + .error(R.mipmap.default_head);//图片加载失败后,显示的图片 + Glide.with(getContext()).load(BuildConfig.HOST_IP_ADDR +UserBean.getUser().getHead()).apply(options).into(mBinding.img); + mBinding.txtName.setText(UserBean.getUser().getUsername()); + mBinding.txtCoin.setText(UserBean.getUser().getCoin()+""); + mBinding.txtSigns.setText(UserBean.getUser().getSign()+""); + mBinding.linGroup.setVisibility(View.VISIBLE); + }else{ + Glide.with(getContext()).load(R.mipmap.default_head).into(mBinding.img); + mBinding.txtName.setText("未登录"); + mBinding.linGroup.setVisibility(View.GONE); + } + setOnClickListener(this,R.id.lin_sign,R.id.lin_coin,R.id.img,R.id.txt_name); + } + + + @Override + public void onClick(View view) { + switch (view.getId()){ + case R.id.img: + openAlthum(); + break; + case R.id.txt_name://名称 + mViewModel.updateName(new HttpObserver() { + @Override + protected void onSuccess(Object data) { + UserBean.getUser().setUsername(data.toString()); + mBinding.txtName.setText(data.toString()); + + } + }); + break; + /* case R.id.lin_coin://金币 + new BottomMenuFragment(getActivity()) + .addMenuItems(new MenuItem("查看记录")) + .addMenuItems(new MenuItem("申请提现")) + .setOnItemClickListener(new BottomMenuFragment.OnItemClickListener() { + @Override + public void onItemClick(TextView menu_item, int position) { + if(position == 0){ + startActivity(new Intent(mActivity, CoinRecordActivity.class) ); + }else { + if(mActivity.isNull(UserBean.getUser().getAlipay())){ + mActivity.showDialog("设置支付宝", "您还没有设置支付宝账号", "设置", "取消", new ResPonse() { + @Override + public void doSuccess(Object obj) { + startActivity(new Intent(mActivity, CoinSettingActivity.class) ); + } + }); + }else if(mActivity.isNull(UserBean.getUser().getRealname())){ + mActivity.showDialog("设置真实姓名", "您还没有设置真实姓名", "设置", "取消", new ResPonse() { + @Override + public void doSuccess(Object obj) { + startActivity(new Intent(mActivity, CoinSettingActivity.class) ); + } + }); + }else{ + startActivityForResult(new Intent(mActivity, WithDrawActivity.class),REQUEST_CODE_WITHDRAW ); + } + } + } + }) + .show(); + break; + case R.id.lin_sign://签到 + startActivityForResult(new Intent(getContext(), SignInActivity.class),REQUEST_CODE_SIGN); + break;*/ + } + } + + + /** + * 打开相册 + */ + public void openAlthum(){ + PermissionX.init(this) + .permissions(mActivity.CAMERA_PERMISSIONS) + .request((allGranted, grantedList, deniedList) -> { + if(allGranted){ + PictureSelector + .create(this, PictureSelector.SELECT_REQUEST_CODE) + .selectPicture(true, 300, 300, 20, 20); + }else{ + mActivity.showDialog("警告", "软件需要权限才能运行", "申请权限", "取消", new ResPonse() { + @Override + public void doSuccess(Object obj) { + openAlthum(); + } + + @Override + public void doError(Object obj) { + } + }); + } + + }); + } + + + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + /*结果回调*/ + if (requestCode == PictureSelector.SELECT_REQUEST_CODE) { + if (data != null) { + String picturePath = data.getStringExtra(PictureSelector.PICTURE_PATH); + MyLog.i("mineActivity","picturePath:"+picturePath); + final File file = new File(picturePath); + mViewModel.updateHead(file).enqueue(new Callback<ResponseBody>() { + @Override + public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { + /*UserBean.getUser().setHead(obj.toString()); + file.delete(); + Glide.with(getContext()).load(BuildConfig.HOST_IP_ADDR+UserBean.getUser().getHead()) .into(mBinding.img); //获取选取的图片*/ + + } + + @Override + public void onFailure(Call<ResponseBody> call, Throwable t) { + file.delete(); + } + }); + } + }else if(requestCode == REQUEST_CODE_SIGN && resultCode == Activity.RESULT_OK){ + loadData(); + }else if(requestCode == REQUEST_CODE_WITHDRAW && resultCode == Activity.RESULT_OK){ + loadData(); + } + } + +} diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/mine/MineViewModel.java b/app/src/main/java/com/runt/open/mvvm/ui/main/mine/MineViewModel.java new file mode 100644 index 0000000..0dfb04b --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/ui/main/mine/MineViewModel.java @@ -0,0 +1,36 @@ +package com.runt.open.mvvm.ui.main.mine; + +import com.runt.open.mvvm.base.model.BaseViewModel; +import com.runt.open.mvvm.listener.ResPonse; +import com.runt.open.mvvm.retrofit.observable.HttpObserver; +import com.runt.open.mvvm.ui.login.UserBean; + +import java.io.File; + +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; +import okhttp3.ResponseBody; +import retrofit2.Call; + +/** + * @purpose Created by Runt (qingingrunt2010@qq.com) on 2022/7/27. + */ +public class MineViewModel extends BaseViewModel { + + public void updateName(HttpObserver observer){ + if(UserBean.getUser().getPhone().equals(UserBean.getUser().getUsername())) { + mActivity.showInputDialog("输入名称", UserBean.getUser().getUsername(), "名称只能修改一次", new ResPonse() { + @Override + public void doSuccess(Object obj) { + httpObserverOnLoading(commonApi.updateName(obj.toString()), observer); + } + }); + } + } + + public Call<ResponseBody> updateHead(File file){ + return commonApi.updateHead(MultipartBody.Part.createFormData("head",file.getName(), RequestBody.create(MediaType.parse("text/plain"), file))); + } + +} diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/notifications/NotificationsFragment.java b/app/src/main/java/com/runt/open/mvvm/ui/main/notifications/NotificationsFragment.java deleted file mode 100644 index 29970e8..0000000 --- a/app/src/main/java/com/runt/open/mvvm/ui/main/notifications/NotificationsFragment.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.runt.open.mvvm.ui.main.notifications; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProvider; - -import com.runt.open.mvvm.databinding.FragmentNotificationsBinding; - -public class NotificationsFragment extends Fragment { - - private NotificationsViewModel notificationsViewModel; - private FragmentNotificationsBinding binding; - - public View onCreateView(@NonNull LayoutInflater inflater, - ViewGroup container, Bundle savedInstanceState) { - notificationsViewModel = - new ViewModelProvider(this).get(NotificationsViewModel.class); - - binding = FragmentNotificationsBinding.inflate(inflater, container, false); - View root = binding.getRoot(); - - final TextView textView = binding.textNotifications; - notificationsViewModel.getText().observe(getViewLifecycleOwner(), new Observer<String>() { - @Override - public void onChanged(@Nullable String s) { - textView.setText(s); - } - }); - return root; - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - binding = null; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/notifications/NotificationsViewModel.java b/app/src/main/java/com/runt/open/mvvm/ui/main/notifications/NotificationsViewModel.java deleted file mode 100644 index 7e47f94..0000000 --- a/app/src/main/java/com/runt/open/mvvm/ui/main/notifications/NotificationsViewModel.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.runt.open.mvvm.ui.main.notifications; - -import androidx.lifecycle.LiveData; -import androidx.lifecycle.MutableLiveData; -import androidx.lifecycle.ViewModel; - -public class NotificationsViewModel extends ViewModel { - - private MutableLiveData<String> mText; - - public NotificationsViewModel() { - mText = new MutableLiveData<>(); - mText.setValue("This is notifications fragment"); - } - - public LiveData<String> getText() { - return mText; - } -} \ No newline at end of file diff --git a/app/src/main/java/com/runt/open/mvvm/ui/main/service/ServiceFragment.java b/app/src/main/java/com/runt/open/mvvm/ui/main/service/ServiceFragment.java new file mode 100644 index 0000000..13e0191 --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/ui/main/service/ServiceFragment.java @@ -0,0 +1,63 @@ +package com.runt.open.mvvm.ui.main.service; + +import android.view.View; + +import com.runt.open.mvvm.R; +import com.runt.open.mvvm.base.activities.BaseActivity; +import com.runt.open.mvvm.base.fragments.BaseFragment; +import com.runt.open.mvvm.base.model.ImpViewModel; +import com.runt.open.mvvm.databinding.FragmentServiceBinding; +import com.runt.open.mvvm.listener.ResPonse; + +/** + * @purpose Created by Runt (qingingrunt2010@qq.com) on 2022/7/27. + */ +public class ServiceFragment extends BaseFragment<FragmentServiceBinding, ImpViewModel> implements View.OnClickListener { + + @Override + public void initViews() { + + } + + @Override + public void loadData() { + + } + + @Override + public void onClick(View view) { + switch (view.getId()){ + case R.id.lin_uav: + mActivity.showDialog("联系服务商", "即将拨打服务商电话", "拨打","取消",new ResPonse() { + @Override + public void doSuccess(Object obj) { + mActivity.callPhone("15048325741"); + } + }); + break; + case R.id.lin_bozhong: + showDialog(); + break; + case R.id.lin_yumi: + showDialog(); + break; + case R.id.lin_xiaomai: + showDialog(); + break; + } + } + + public void showDialog(){ + ((BaseActivity)getActivity()).showDialog("暂无服务商", "如果您是相关服务商可致电入住", "入住","取消",new ResPonse() { + @Override + public void doSuccess(Object obj) { + mActivity.showDialog("联系平台", "即将拨打平台电话", "拨打","取消",new ResPonse() { + @Override + public void doSuccess(Object obj) { + mActivity.callPhone("13000000000"); + } + }); + } + }); + } +} diff --git a/app/src/main/java/com/runt/open/mvvm/ui/splash/SplashActivity.java b/app/src/main/java/com/runt/open/mvvm/ui/splash/SplashActivity.java index 988e8b6..bb5fa8f 100644 --- a/app/src/main/java/com/runt/open/mvvm/ui/splash/SplashActivity.java +++ b/app/src/main/java/com/runt/open/mvvm/ui/splash/SplashActivity.java @@ -2,18 +2,12 @@ import android.content.Intent; import android.os.Handler; -import android.os.Message; -import android.util.Log; -import android.view.View; import android.view.WindowManager; -import androidx.annotation.NonNull; -import androidx.lifecycle.Observer; - -import com.bytedance.sdk.openadsdk.TTSplashAd; -import com.runt.open.mvvm.MainActivity; import com.runt.open.mvvm.base.activities.BaseActivity; +import com.runt.open.mvvm.base.model.ImpViewModel; import com.runt.open.mvvm.databinding.ActivitySplashBinding; +import com.runt.open.mvvm.ui.main.MainActivity; /** @@ -21,73 +15,26 @@ * * @purpose Created by Runt (qingingrunt2010@qq.com) on 2020-4-16. */ -public class SplashActivity extends BaseActivity<ActivitySplashBinding,SplashViewModel> { +public class SplashActivity extends BaseActivity<ActivitySplashBinding, ImpViewModel> { final String TAG = "WelcomeActivity"; - - Handler handler = new Handler(){ - boolean started = false; - @Override - public void handleMessage(@NonNull Message msg) { - super.handleMessage(msg); - if(!started) {//确保该语句只执行一次 - started = true; - Intent intent = new Intent(mContext, MainActivity.class); - startActivity(intent); - finish(); - } - } - }; - @Override public void initViews() { getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏 hideBottomUIMenu(); - viewModel.getSplashAd().observe(this, new Observer<TTSplashAd>() { - @Override - public void onChanged(TTSplashAd ttSplashAd) { - binding.splashAdContainer.addView(ttSplashAd.getSplashView()); - //设置SplashView的交互监听器 - ttSplashAd.setSplashInteractionListener(new TTSplashAd.AdInteractionListener() { - @Override - public void onAdClicked(View view, int type) { - Log.d(TAG, "onAdClicked"); - } - - @Override - public void onAdShow(View view, int type) { - Log.d(TAG, "onAdShow"); - } - - @Override - public void onAdSkip() { - Log.d(TAG, "onAdSkip"); - handler.sendMessage(new Message()); - - } - - @Override - public void onAdTimeOver() { - Log.d(TAG, "onAdTimeOver"); - handler.sendMessage(new Message()); - } - }); - } - }); - viewModel.getTimeOut().observe(this, new Observer<Integer>() { - @Override - public void onChanged(Integer integer) { - handler.sendMessage(new Message()); - } - }); - viewModel.applyTdAd(mContext);;//请求广告 } - @Override - protected void onDestroy() { - super.onDestroy(); - binding.splashAdContainer.removeAllViews(); + public void loadData() { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + Intent intent = new Intent(mContext, MainActivity.class); + startActivity(intent); + finish(); + } + },2000); } + } diff --git a/app/src/main/java/com/runt/open/mvvm/ui/splash/SplashViewModel.java b/app/src/main/java/com/runt/open/mvvm/ui/splash/SplashViewModel.java index 61e73d0..5d1c2c7 100644 --- a/app/src/main/java/com/runt/open/mvvm/ui/splash/SplashViewModel.java +++ b/app/src/main/java/com/runt/open/mvvm/ui/splash/SplashViewModel.java @@ -1,15 +1,9 @@ package com.runt.open.mvvm.ui.splash; -import android.content.Context; import android.os.Handler; -import android.util.Log; import androidx.lifecycle.MutableLiveData; -import com.bytedance.sdk.openadsdk.AdSlot; -import com.bytedance.sdk.openadsdk.TTAdNative; -import com.bytedance.sdk.openadsdk.TTAdSdk; -import com.bytedance.sdk.openadsdk.TTSplashAd; import com.runt.open.mvvm.base.model.BaseViewModel; import java.util.Date; @@ -22,12 +16,8 @@ final String TAG = "SplashViewModel"; long cTime = new Date().getTime(),limitTime = 2000; - private MutableLiveData<TTSplashAd> splashAd = new MutableLiveData<>(); private MutableLiveData<Integer> timeOut = new MutableLiveData<>(); - public MutableLiveData<TTSplashAd> getSplashAd() { - return splashAd; - } public MutableLiveData<Integer> getTimeOut() { return timeOut; @@ -42,46 +32,5 @@ },limitTime); } - /** - * 请求广告 - * @param context - */ - public void applyTdAd(Context context){ - countdown(); - TTAdNative mTTAdNative = TTAdSdk.getAdManager().createAdNative(context); - AdSlot adSlot = new AdSlot.Builder() - .setCodeId("887382769")//广告id - .setSupportDeepLink(true) - .setImageAcceptedSize(1080,1920) - //模板广告需要设置期望个性化模板广告的大小,单位dp,代码位是否属于个性化模板广告,请在穿山甲平台查看 - //.setExpressViewAcceptedSize(expressViewWidth, expressViewHeight) - .build(); - mTTAdNative.loadSplashAd(adSlot,new TTAdNative.SplashAdListener() { - @Override - public void onError(int i, String s) { - Log.i(TAG,"code:"+i+" message:"+s); - } - - @Override - public void onTimeout() { - Log.i(TAG,"超时"); - } - - @Override - public void onSplashAdLoad(TTSplashAd ttSplashAd) { - Log.d(TAG, "开屏广告请求成功"); - - long waitTime = limitTime - (new Date().getTime() - cTime); - if(waitTime > 0){//是否超过限定时间 没有超时则继续 - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - splashAd.setValue(ttSplashAd); - } - }, waitTime > 0 ? waitTime : 0); - } - } - }); - } } diff --git a/app/src/main/java/com/runt/open/mvvm/ui/web/WebViewActivity.java b/app/src/main/java/com/runt/open/mvvm/ui/web/WebViewActivity.java index d41521c..f27491f 100644 --- a/app/src/main/java/com/runt/open/mvvm/ui/web/WebViewActivity.java +++ b/app/src/main/java/com/runt/open/mvvm/ui/web/WebViewActivity.java @@ -33,59 +33,64 @@ initCompent(); } + @Override + public void loadData() { + + } + int count = 100; int index = 100; private void initCompent(){ - binding.browser.getSettings().setJavaScriptEnabled(true); - binding.browser.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); + mBinding.browser.getSettings().setJavaScriptEnabled(true); + mBinding.browser.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN); //跳转至拼接好的地址 //mBaseHandler.sendMessage(msg);//http://192.168.5.156:8080/MyFinance/gd16/1.html - binding.browser.loadUrl(url); - binding.browser.setWebViewClient(new myWebViewClient()); - binding.browser.setWebChromeClient(new WebChromeClient(){ + mBinding.browser.loadUrl(url); + mBinding.browser.setWebViewClient(new myWebViewClient()); + mBinding.browser.setWebChromeClient(new WebChromeClient(){ @Override public void onProgressChanged(WebView view,final int newProgress) { MyLog.i("onProgressChanged","--newProgress:--"+newProgress); - MyLog.i("onProgressChanged","--binding.viewProgressbar:--"+binding.viewProgressbar.getWidth()); + MyLog.i("onProgressChanged","--binding.viewProgressbar:--"+ mBinding.viewProgressbar.getWidth()); final LayoutAnimationController.AnimationParameters animation= new LayoutAnimationController.AnimationParameters(); //得到一个LayoutAnimationController对象; animation.index =index++ ; animation.count = count++ ; if (newProgress == 100) { - MyAnimations.hideAnimaInSitu(binding.linProgressbar); - MyAnimations.makeViewMove(binding.viewProgressbar.getTranslationX(),0,0,0,binding.viewProgressbar); + MyAnimations.hideAnimaInSitu(mBinding.linProgressbar); + MyAnimations.makeViewMove(mBinding.viewProgressbar.getTranslationX(),0,0,0, mBinding.viewProgressbar); new Handler().postDelayed(new Runnable() { @Override public void run() { - binding.linProgressbar.setVisibility(View.GONE); + mBinding.linProgressbar.setVisibility(View.GONE); } },MyAnimations.ANIMA_TIME); } else { - if (View.VISIBLE != binding.linProgressbar.getVisibility()) { - MyAnimations.showAnimaInSitu(binding.linProgressbar); + if (View.VISIBLE != mBinding.linProgressbar.getVisibility()) { + MyAnimations.showAnimaInSitu(mBinding.linProgressbar); if(linProgressWidth==0){ - final ViewTreeObserver vto = binding.linProgressbar.getViewTreeObserver(); + final ViewTreeObserver vto = mBinding.linProgressbar.getViewTreeObserver(); vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { public boolean onPreDraw() { - linProgressWidth = binding.linProgressbar.getMeasuredWidth(); - binding.viewProgressbar.setTranslationX(0-linProgressWidth); - binding.linProgressbar.getViewTreeObserver().removeOnPreDrawListener(this); + linProgressWidth = mBinding.linProgressbar.getMeasuredWidth(); + mBinding.viewProgressbar.setTranslationX(0-linProgressWidth); + mBinding.linProgressbar.getViewTreeObserver().removeOnPreDrawListener(this); return true; } }); }else{ - binding.viewProgressbar.setTranslationX(0-linProgressWidth); + mBinding.viewProgressbar.setTranslationX(0-linProgressWidth); } } if(linProgressWidth!=0){ - MyAnimations.makeViewMove(binding.viewProgressbar.getTranslationX(),0-linProgressWidth+linProgressWidth/100*newProgress,0,0,binding.viewProgressbar,MyAnimations.ANIMA_TIME*3); + MyAnimations.makeViewMove(mBinding.viewProgressbar.getTranslationX(),0-linProgressWidth+linProgressWidth/100*newProgress,0,0, mBinding.viewProgressbar,MyAnimations.ANIMA_TIME*3); new Handler().postDelayed(new Runnable() { @Override public void run() { - MyAnimations.makeViewMove(binding.viewProgressbar.getTranslationX(),binding.viewProgressbar.getTranslationX()+300,0,0,binding.viewProgressbar,MyAnimations.ANIMA_TIME*10); + MyAnimations.makeViewMove(mBinding.viewProgressbar.getTranslationX(), mBinding.viewProgressbar.getTranslationX()+300,0,0, mBinding.viewProgressbar,MyAnimations.ANIMA_TIME*10); } },MyAnimations.ANIMA_TIME*3); } @@ -96,9 +101,9 @@ }); - binding.browser.getSettings().setSavePassword(false); + mBinding.browser.getSettings().setSavePassword(false); //Toast.makeText(mContext,"进入浏览器",Toast.LENGTH_SHORT).show(); - String Scale = String.valueOf(binding.browser.getScale()); + String Scale = String.valueOf(mBinding.browser.getScale()); MyLog.i("Runt","--Scale:--"+Scale); int screenDensity=getResources().getDisplayMetrics().densityDpi; MyLog.i("Runt", "--screenDensity:--"+String.valueOf(screenDensity)); //60-160-240 @@ -147,12 +152,12 @@ } private void hideProgressBar(){ - MyAnimations.hideAnimaInSitu(binding.linProgressbar); - MyAnimations.makeViewMove(binding.viewProgressbar.getTranslationX(),0,0,0,binding.viewProgressbar); + MyAnimations.hideAnimaInSitu(mBinding.linProgressbar); + MyAnimations.makeViewMove(mBinding.viewProgressbar.getTranslationX(),0,0,0, mBinding.viewProgressbar); new Handler().postDelayed(new Runnable() { @Override public void run() { - binding.linProgressbar.setVisibility(View.GONE); + mBinding.linProgressbar.setVisibility(View.GONE); } },MyAnimations.ANIMA_TIME*2); } diff --git a/app/src/main/java/com/runt/open/mvvm/util/DeviceUtil.java b/app/src/main/java/com/runt/open/mvvm/util/DeviceUtil.java index 58761bb..fc5a85c 100644 --- a/app/src/main/java/com/runt/open/mvvm/util/DeviceUtil.java +++ b/app/src/main/java/com/runt/open/mvvm/util/DeviceUtil.java @@ -371,4 +371,61 @@ } return ""; } + + /** + * check the system is harmony os + * + * @return true if it is harmony os + */ + public static boolean isHarmonyOS() { + try { + Class clz = Class.forName("com.huawei.system.BuildEx"); + Method method = clz.getMethod("getOsBrand"); + return "harmony".equals(method.invoke(clz)); + } catch (ClassNotFoundException e) { + Log.e(TAG, "occured ClassNotFoundException"); + } catch (NoSuchMethodException e) { + Log.e(TAG, "occured NoSuchMethodException"); + } catch (Exception e) { + Log.e(TAG, "occur other problem"); + } + return false; + } + + /** + * 获取鸿蒙系统版本号 + */ + public static String getHarmonyOsVersion() { + if (isHarmonyOS()) { + try { + Class cls = Class.forName("android.os.SystemProperties"); + Method method = cls.getMethod("get", String.class); + return method.invoke(cls, "ro.huawei.build.display.id").toString(); + //android.os.Build.DISPLAY + } catch ( Exception e) { + } + } + return "-1"; + } + + /** + * 获取属性 + * @param property + * @param defaultValue + * @return + */ + private static String getProp(String property, String defaultValue) { + try { + Class spClz = Class.forName("android.os.SystemProperties"); + Method method = spClz.getDeclaredMethod("get", String.class); + String value = (String) method.invoke(spClz, property); + if (TextUtils.isEmpty(value)) { + return defaultValue; + } + return value; + } catch (Throwable e) { + e.printStackTrace(); + } + return defaultValue; + } } diff --git a/app/src/main/java/com/runt/open/mvvm/util/HandleDate.java b/app/src/main/java/com/runt/open/mvvm/util/HandleDate.java new file mode 100644 index 0000000..98e9010 --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/util/HandleDate.java @@ -0,0 +1,216 @@ +package com.runt.open.mvvm.util; + +import java.sql.Timestamp; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * @purpose Created by Runt (qingingrunt2010@qq.com) on 2022/7/27. + */ +public class HandleDate { + + private static SimpleDateFormat secondsdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private static SimpleDateFormat timesdf = new SimpleDateFormat("HH:mm:ss"); + private static SimpleDateFormat datesdf = new SimpleDateFormat("yyyy-MM-dd"); + private static SimpleDateFormat hoursdf = new SimpleDateFormat("yyyy-MM-dd HH"); + private static SimpleDateFormat minutesdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + + /** + * 获取当前时间的String类型 + */ + public static long getDateToLong() { + return new Date().getTime(); + } + + /** + * 获取指定时间的long类型 + */ + public static long getDateToLong(Date date) { + + return date.getTime(); + } + + /** + * 获取指定时间的long类型 + * + * @throws ParseException + */ + public static long getDateToLong(String datestr) throws ParseException { + + return datesdf.parse(datestr).getTime(); + } + + /** + * 将long类型的时间转换成只有日期的int类型 + */ + public static int getDateToInt(long datetime) { + + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); + Date date = getLongToDate(datetime); + String format = sdf.format(date); + return Integer.parseInt(format); + } + + /** + * 将指定long类型的日期转换为date + */ + public static Date getLongToDate(Long datetime) { + return new Date(datetime); + } + + /** + * 将指定long类型的日期转换为string时间精确到秒 + */ + public static String getLongToSecond(Long datetime) { + Date date = new Date(datetime); + return secondsdf.format(date); + } + + /** + * 将指定long类型的日期转换为string时间 只显示 时分秒 + */ + public static String getLongToTime(Long datetime) { + String datestr = ""; + Date date = null; + try { + date = new Date(datetime); + datestr = timesdf.format(date); + } catch (Exception e) { + e.printStackTrace(); + } + return datestr; + } + + /** + * 将指定long类型的日期转换为string时间只显示日期 + */ + public static String getLongToDatestr(Long datetime) { + String datestr = ""; + Date date = null; + try { + date = new Date(datetime); + datestr = datesdf.format(date); + } catch (Exception e) { + e.printStackTrace(); + } + return datestr; + } + + /** + * 将指定long类型的日期转换为string时间精确到小时 + */ + public static String getLongToHour(Long datetime) { + String datestr = ""; + Date date = null; + try { + date = new Date(datetime); + datestr = hoursdf.format(date); + } catch (Exception e) { + e.printStackTrace(); + } + return datestr; + } + + /** + * 将指定long类型的日期转换为string日期 + */ + public static String getLongToSimpleDate(Long datetime) { + String datestr = ""; + Date date = null; + try { + date = new Date(datetime); + datestr = datesdf.format(date); + } catch (Exception e) { + e.printStackTrace(); + } + return datestr; + } + + /** + * 根据毫秒时间戳来格式化字符串 今天显示今天、昨天显示昨天、前天显示前天. 早于前天的显示具体年-月-日,如2017-06-12; + * + * @param timeStamp 毫秒值 + * @return 今天 昨天 前天 或者 yyyy-MM-dd HH:mm:ss类型字符串 + */ + public static String format(long timeStamp) { + long curTimeMillis = System.currentTimeMillis(); + Date curDate = new Date(curTimeMillis); + int todayHoursSeconds = curDate.getHours() * 60 * 60; + int todayMinutesSeconds = curDate.getMinutes() * 60; + int todaySeconds = curDate.getSeconds(); + int todayMillis = (todayHoursSeconds + todayMinutesSeconds + todaySeconds) * 1000; + long todayStartMillis = curTimeMillis - todayMillis; + if (timeStamp >= todayStartMillis) { + return "今天"; + } + int oneDayMillis = 24 * 60 * 60 * 1000; + long yesterdayStartMilis = todayStartMillis - oneDayMillis; + if (timeStamp >= yesterdayStartMilis) { + return "昨天"; + } + long yesterdayBeforeStartMilis = yesterdayStartMilis - oneDayMillis; + if (timeStamp >= yesterdayBeforeStartMilis) { + return "前天"; + } + // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); + return sdf.format(new Date(timeStamp)); + } + + /** + * 根据时间戳来判断当前的时间是几天前,几分钟,刚刚 + * + * @param long_time + * @return + */ + + public static String getTimeStateNew(String long_time) { + String long_by_13 = "1000000000000"; + String long_by_10 = "1000000000"; + if (Long.valueOf(long_time) / Long.valueOf(long_by_13) < 1) { + if (Long.valueOf(long_time) / Long.valueOf(long_by_10) >= 1) { + long_time = long_time + "000"; + } + } + return getTimeStateNew(long_time); + } + public static String getTimeStateNew(Date long_time) { + return getTimeStateNew(long_time.getTime() ); + } + public static String getTimeStateNew(Long long_time) { + Timestamp time = new Timestamp(Long.valueOf(long_time)); + Timestamp now = new Timestamp(System.currentTimeMillis()); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); + // System.out.println("传递过来的时间:"+format.format(time)); + // System.out.println("现在的时间:"+format.format(now)); + long day_conver = 1000 * 60 * 60 * 24; + long hour_conver = 1000 * 60 * 60; + long min_conver = 1000 * 60; + long time_conver = now.getTime() - time.getTime(); + long temp_conver; + // System.out.println("天数:"+time_conver/day_conver); + if ((time_conver / day_conver) < 3) { + temp_conver = time_conver / day_conver; + if (temp_conver <= 2 && temp_conver >= 1) { + return temp_conver + "天前"; + } else { + temp_conver = (time_conver / hour_conver); + if (temp_conver >= 1) { + return temp_conver + "小时前"; + } else { + temp_conver = (time_conver / min_conver); + if (temp_conver >= 1) { + return temp_conver + "分钟前"; + } else { + return "刚刚"; + } + } + } + } else { + return format.format(time); + } + } + + +} diff --git a/app/src/main/java/com/runt/open/mvvm/widgets/CircleImageView.java b/app/src/main/java/com/runt/open/mvvm/widgets/CircleImageView.java new file mode 100644 index 0000000..fece7e8 --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/widgets/CircleImageView.java @@ -0,0 +1,245 @@ +package com.runt.open.mvvm.widgets; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.widget.ImageView; + +import com.runt.open.mvvm.R; + + +/** + * My father is Object, ites purpose of 圆形图片带阴影 + * + * @purpose Created by Runt (qingingrunt2010@qq.com) on 2020-2-23. + */ +@SuppressLint("AppCompatCustomView") +public class CircleImageView extends ImageView { + + private static final ScaleType SCALE_TYPE = ScaleType.CENTER_CROP; + + private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; + private static final int COLORDRAWABLE_DIMENSION = 1; + + private static final int DEFAULT_BORDER_WIDTH = 0; + private static final int DEFAULT_BORDER_COLOR = Color.BLACK; + + private final RectF mDrawableRect = new RectF(); + private final RectF mBorderRect = new RectF(); + + private final Matrix mShaderMatrix = new Matrix(); + private final Paint mBitmapPaint = new Paint(); + private final Paint mBorderPaint = new Paint(); + + private int mBorderColor = DEFAULT_BORDER_COLOR; + private int mBorderWidth = DEFAULT_BORDER_WIDTH; + + private Bitmap mBitmap; + private BitmapShader mBitmapShader; + private int mBitmapWidth; + private int mBitmapHeight; + + private float mDrawableRadius; + private float mBorderRadius; + + private boolean mReady; + private boolean mSetupPending; + + public CircleImageView(Context context) { + super(context); + } + + public CircleImageView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CircleImageView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + super.setScaleType(SCALE_TYPE); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView, defStyle, 0); + + mBorderWidth = a.getDimensionPixelSize(R.styleable.CircleImageView_border_width, DEFAULT_BORDER_WIDTH); + mBorderColor = a.getColor(R.styleable.CircleImageView_border_color, DEFAULT_BORDER_COLOR); + + a.recycle(); + + mReady = true; + + if (mSetupPending) { + setup(); + mSetupPending = false; + } + } + + @Override + public ScaleType getScaleType() { + return SCALE_TYPE; + } + + @Override + public void setScaleType(ScaleType scaleType) { + if (scaleType != SCALE_TYPE) { + throw new IllegalArgumentException(String.format("ScaleType %s not supported.", scaleType)); + } + } + + @Override + protected void onDraw(Canvas canvas) { + if (getDrawable() == null) { + return; + } + + canvas.drawCircle(getWidth() / 2, getHeight() / 2, mDrawableRadius, mBitmapPaint); + if(getBorderWidth()>0) { + canvas.drawCircle(getWidth() / 2, getHeight() / 2, mBorderRadius, mBorderPaint); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + setup(); + } + + public int getBorderColor() { + return mBorderColor; + } + + public void setBorderColor(int borderColor) { + if (borderColor == mBorderColor) { + return; + } + + mBorderColor = borderColor; + mBorderPaint.setColor(mBorderColor); + invalidate(); + } + + public int getBorderWidth() { + return mBorderWidth; + } + + public void setBorderWidth(int borderWidth) { + if (borderWidth == mBorderWidth) { + return; + } + + mBorderWidth = borderWidth; + setup(); + } + + @Override + public void setImageBitmap(Bitmap bm) { + super.setImageBitmap(bm); + mBitmap = bm; + setup(); + } + + @Override + public void setImageDrawable(Drawable drawable) { + super.setImageDrawable(drawable); + mBitmap = getBitmapFromDrawable(drawable); + setup(); + } + + @Override + public void setImageResource(int resId) { + super.setImageResource(resId); + mBitmap = getBitmapFromDrawable(getDrawable()); + setup(); + } + + private Bitmap getBitmapFromDrawable(Drawable drawable) { + if (drawable == null) { + return null; + } + + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + + try { + Bitmap bitmap; + + if (drawable instanceof ColorDrawable) { + bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG); + } else { + bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG); + } + + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } catch (OutOfMemoryError e) { + return null; + } + } + + private void setup() { + if (!mReady) { + mSetupPending = true; + return; + } + + if (mBitmap == null) { + return; + } + + mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + + mBitmapPaint.setAntiAlias(true); + mBitmapPaint.setShader(mBitmapShader); + + mBorderPaint.setStyle(Paint.Style.STROKE); + mBorderPaint.setAntiAlias(true); + mBorderPaint.setColor(mBorderColor); + mBorderPaint.setStrokeWidth(mBorderWidth); + + mBitmapHeight = mBitmap.getHeight(); + mBitmapWidth = mBitmap.getWidth(); + + mBorderRect.set(0, 0, getWidth(), getHeight()); + mBorderRadius = Math.min((mBorderRect.height() - mBorderWidth) / 2, (mBorderRect.width() - mBorderWidth) / 2); + + mDrawableRect.set(mBorderWidth, mBorderWidth, mBorderRect.width() - mBorderWidth, mBorderRect.height() - mBorderWidth); + mDrawableRadius = Math.min(mDrawableRect.height() / 2, mDrawableRect.width() / 2); + + updateShaderMatrix(); + invalidate(); + } + + private void updateShaderMatrix() { + float scale; + float dx = 0; + float dy = 0; + + mShaderMatrix.set(null); + + if (mBitmapWidth * mDrawableRect.height() > mDrawableRect.width() * mBitmapHeight) { + scale = mDrawableRect.height() / (float) mBitmapHeight; + dx = (mDrawableRect.width() - mBitmapWidth * scale) * 0.5f; + } else { + scale = mDrawableRect.width() / (float) mBitmapWidth; + dy = (mDrawableRect.height() - mBitmapHeight * scale) * 0.5f; + } + + mShaderMatrix.setScale(scale, scale); + mShaderMatrix.postTranslate((int) (dx + 0.5f) + mBorderWidth, (int) (dy + 0.5f) + mBorderWidth); + + mBitmapShader.setLocalMatrix(mShaderMatrix); + } +} diff --git a/app/src/main/java/com/runt/open/mvvm/widgets/CornerImageView.java b/app/src/main/java/com/runt/open/mvvm/widgets/CornerImageView.java new file mode 100644 index 0000000..a9be0cb --- /dev/null +++ b/app/src/main/java/com/runt/open/mvvm/widgets/CornerImageView.java @@ -0,0 +1,163 @@ +package com.runt.open.mvvm.widgets; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.util.AttributeSet; + +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; + + +/** + * My father is Object, ites purpose of 圆角 + * + * @purpose Created by Runt (qingingrunt2010@qq.com) on 2020-6-18. + */ +public class CornerImageView extends AppCompatImageView { + + private int cornerSize = 30; + + private Paint paint; + + public CornerImageView(Context context) { + + super(context); + + paint = new Paint(); + + paint.setColor(Color.WHITE); + + paint.setAntiAlias(true);//消除锯齿 + + } + + public CornerImageView(Context context, @Nullable AttributeSet attrs) { + + super(context, attrs); + + paint = new Paint(); + + paint.setColor(Color.WHITE); + + paint.setAntiAlias(true);//消除锯齿 + + } + + @Override + + public void draw(Canvas canvas) { + + super.draw(canvas); + + drawLeftTop(canvas); + + drawRightTop(canvas); + + drawLeftBottom(canvas); + + drawRightBottom(canvas); + + } + + private void drawLeftTop(Canvas canvas) { + + Path path = new Path(); + + path.moveTo(0, cornerSize); + + path.lineTo(0, 0); + + path.lineTo(cornerSize, 0); + + path.arcTo(new RectF(0, 0, cornerSize * 2, cornerSize * 2), -90, -90); + + path.close(); + + canvas.drawPath(path, paint); + + } + + private void drawLeftBottom(Canvas canvas) { + + Path path = new Path(); + + path.moveTo(0, getHeight() - cornerSize); + + path.lineTo(0, getHeight()); + + path.lineTo(cornerSize, getHeight()); + + path.arcTo(new RectF(0, // x + + getHeight() - cornerSize * 2,// y + + cornerSize * 2,// x + + getHeight()// getWidth()// y + + ), 90, 90); + + path.close(); + + canvas.drawPath(path, paint); + + } + + private void drawRightBottom(Canvas canvas) { + + Path path = new Path(); + + path.moveTo(getWidth() - cornerSize, getHeight()); + + path.lineTo(getWidth(), getHeight()); + + path.lineTo(getWidth(), getHeight() - cornerSize); + + RectF oval = new RectF(getWidth() - cornerSize * 2, getHeight() + + - cornerSize * 2, getWidth(), getHeight()); + + path.arcTo(oval, 0, 90); + + path.close(); + + canvas.drawPath(path, paint); + + } + + private void drawRightTop(Canvas canvas) { + + Path path = new Path(); + + path.moveTo(getWidth(), cornerSize); + + path.lineTo(getWidth(), 0); + + path.lineTo(getWidth() - cornerSize, 0); + + path.arcTo(new RectF(getWidth() - cornerSize * 2, 0, getWidth(), + + 0 + cornerSize * 2), -90, 90); + + path.close(); + + canvas.drawPath(path, paint); + + } + + public int getCornerSize() { + + return cornerSize; + + } + + public void setCornerSize(int cornerSize) { + + this.cornerSize = cornerSize; + + } +} diff --git a/app/src/main/java/com/runt/open/mvvm/widgets/TitleBarView.java b/app/src/main/java/com/runt/open/mvvm/widgets/TitleBarView.java index 746b72a..df3fd5a 100644 --- a/app/src/main/java/com/runt/open/mvvm/widgets/TitleBarView.java +++ b/app/src/main/java/com/runt/open/mvvm/widgets/TitleBarView.java @@ -67,6 +67,14 @@ rightTextSize = array.getDimension(R.styleable.TitleBarView_rightTextSize, DimensionUtils.convertSpToPixel(getContext(),14)); rightPadding = array.getDimension(R.styleable.TitleBarView_rightDrawablePadding,10); + int leftTint = array.getColor(R.styleable.TitleBarView_leftTint,-1); + if(leftTint != -1) { + setTint(leftDra,leftTint); + } + int rightTint = array.getColor(R.styleable.TitleBarView_rightTint,-1); + if(rightTint != -1) { + setTint(rightDra,rightTint); + } textPaint = new Paint(); textPaint.setAntiAlias(true); // 是否抗锯齿 //mTextPaint.setAlpha(50); // 设置alpha不透明度,范围为0~255 @@ -253,4 +261,10 @@ float height2 = fm.bottom - fm.top + fm.leading;//行高 return (int) height2; } + + private void setTint(Drawable drawable, @ColorInt int color){ + if(drawable!= null){ + drawable.setTint(color); + } + } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 964ea3f..deb81e7 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -2,19 +2,25 @@ <androidx.constraintlayout.widget.ConstraintLayout 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" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" > <com.runt.open.mvvm.widgets.TitleBarView android:id="@+id/title_bar" - android:layout_width="match_parent" - android:layout_height="?attr/actionBarSize" - android:background="@color/white" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toRightOf="parent" /> + style="@style/titlebar" + tools:ignore="MissingConstraints" + app:titleText="标题" /> + <androidx.viewpager2.widget.ViewPager2 + android:id="@+id/view_pager_2" + android:layout_width="match_parent" + android:layout_height="0dp" + app:layout_constraintTop_toBottomOf="@id/title_bar" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + app:layout_constraintBottom_toTopOf="@id/nav_view" /> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/nav_view" android:layout_width="0dp" @@ -27,17 +33,5 @@ app:layout_constraintRight_toRightOf="parent" app:menu="@menu/bottom_nav_menu"/> - <fragment - android:id="@+id/nav_host_fragment_activity_main" - android:name="androidx.navigation.fragment.NavHostFragment" - android:layout_width="match_parent" - android:layout_height="match_parent" - app:defaultNavHost="true" - app:layout_constraintBottom_toTopOf="@id/nav_view" - app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toRightOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:navGraph="@navigation/mobile_navigation" - /> </androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_setting.xml b/app/src/main/res/layout/activity_setting.xml new file mode 100644 index 0000000..6159993 --- /dev/null +++ b/app/src/main/res/layout/activity_setting.xml @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout 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" + android:background="@color/white" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <com.runt.open.mvvm.widgets.TitleBarView + android:id="@+id/title_bar" + style="@style/titlebar" + tools:ignore="MissingConstraints" + app:titleText="设置" + app:leftDrawable="@mipmap/icon_white_back" + app:leftTint="@color/black"/> + + <TextView + android:id="@+id/version" + app:layout_constraintTop_toBottomOf="@id/title_bar" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + android:background="@drawable/bg_white" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="left" + android:text="@string/str_version" + android:textColor="@color/txt_color" + android:textSize="@dimen/title_size" + android:padding="15dp" /> + <TextView + android:id="@+id/about" + app:layout_constraintTop_toBottomOf="@id/version" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + android:background="@drawable/bg_white" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:drawableRight="@mipmap/arrow_right" + android:gravity="left" + android:text="关于我们" + android:textColor="@color/txt_color" + android:textSize="@dimen/title_size" + android:padding="15dp" /> + <View + app:layout_constraintTop_toBottomOf="@id/title_bar" + android:layout_width="match_parent" + android:layout_height="0.5dp" + android:background="@color/color_gray8" /> + <View + app:layout_constraintTop_toBottomOf="@id/version" + android:layout_width="match_parent" + android:layout_height="0.5dp" + android:background="@color/color_gray8" /> + <View + app:layout_constraintTop_toBottomOf="@id/about" + android:layout_width="match_parent" + android:layout_height="0.5dp" + android:background="@color/color_gray8" /> + + <View + app:layout_constraintBottom_toTopOf="@id/logout" + android:layout_width="match_parent" + android:layout_height="1dp" + android:background="@color/color_gray8" /> + <TextView + android:id="@+id/logout" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + android:background="@drawable/bg_white" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center" + android:text="@string/logout" + android:textColor="@color/txt_color" + android:textSize="@dimen/title_size" + android:padding="15dp" /> +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_splash.xml b/app/src/main/res/layout/activity_splash.xml index 70a0b97..ad20990 100644 --- a/app/src/main/res/layout/activity_splash.xml +++ b/app/src/main/res/layout/activity_splash.xml @@ -13,9 +13,5 @@ android:scaleType="centerCrop" /> - <FrameLayout - android:id="@+id/splash_ad_container" - android:layout_width="match_parent" - android:layout_height="match_parent" /> </RelativeLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/activity_web.xml b/app/src/main/res/layout/activity_web.xml index c3ad397..34531b1 100644 --- a/app/src/main/res/layout/activity_web.xml +++ b/app/src/main/res/layout/activity_web.xml @@ -1,15 +1,14 @@ <?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <com.runt.open.mvvm.widgets.TitleBarView android:id="@+id/title_bar" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toRightOf="parent" - style="@style/titlebar" /> + style="@style/titlebar" + tools:ignore="MissingConstraints" /> <LinearLayout android:id="@+id/lin_progressbar" diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_dashboard.xml deleted file mode 100644 index 53e0e0c..0000000 --- a/app/src/main/res/layout/fragment_dashboard.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout - 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" - android:layout_width="match_parent" - android:layout_height="match_parent" - tools:context=".ui.main.dashboard.DashboardFragment" > - - <TextView - android:id="@+id/text_dashboard" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="8dp" - android:textAlignment="center" - android:textSize="20sp" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" /> -</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml deleted file mode 100644 index 02db4bd..0000000 --- a/app/src/main/res/layout/fragment_home.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout - 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" - android:layout_width="match_parent" - android:layout_height="match_parent" - tools:context=".ui.main.home.HomeFragment" > - - <TextView - android:id="@+id/text_home" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="8dp" - android:textAlignment="center" - android:textSize="20sp" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" /> -</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_mine.xml b/app/src/main/res/layout/fragment_mine.xml new file mode 100644 index 0000000..c3dc06a --- /dev/null +++ b/app/src/main/res/layout/fragment_mine.xml @@ -0,0 +1,191 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:background="@color/white" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + tools:ignore="MissingDefaultResource"> + + <ScrollView + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <LinearLayout + + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <View + android:layout_width="match_parent" + android:layout_height="0.5dp" + android:background="@color/color_gray8" /> + <LinearLayout + android:id="@+id/lin_name" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:background="@drawable/bg_white" > + + <ImageView + android:id="@+id/img_top_bg" + android:layout_width="match_parent" + android:layout_height="200dp" + android:scaleType="centerCrop" + android:src="@mipmap/user_back"/> + + <com.runt.open.mvvm.widgets.CircleImageView + android:id="@+id/img" + android:layout_width="100dp" + android:layout_height="100dp" + android:layout_gravity="center_horizontal" + android:layout_marginTop="-50dp" + android:scaleType="centerCrop" + android:src="@mipmap/default_head" /> + <TextView + android:id="@+id/txt_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginTop="10dp" + android:text="名称" + android:textSize="20sp" + android:textColor="@color/txt_normal"/> + <TextView + android:id="@+id/txt_user_sign" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center_horizontal" + android:layout_marginTop="10dp" + android:paddingLeft="15dp" + android:paddingRight="15dp" + android:gravity="center" + android:text="签名" + android:textSize="16sp" + android:visibility="gone" + android:drawablePadding="20dp" + android:textColor="@color/txt_enable"/> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_margin="15dp" + android:visibility="gone" + android:orientation="horizontal"> + + <TextView + style="@style/user_txt_left" + android:drawableLeft="@mipmap/location_e" + android:text="所在地:"/> + <TextView + android:id="@+id/txt_address" + style="@style/user_txt_value" + android:text="北京"/> + + </LinearLayout> + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="15dp" + android:visibility="gone" + android:orientation="horizontal"> + + <TextView + style="@style/user_txt_left" + android:drawableLeft="@mipmap/birth" + android:text="年龄:"/> + <TextView + android:id="@+id/txt_age" + style="@style/user_txt_value" + android:text="11"/> + + </LinearLayout> + + <LinearLayout + android:id="@+id/lin_group" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@drawable/white_corner_border" + android:layout_margin="@dimen/default_margin_lr" + android:elevation="5dp"> + + + <LinearLayout + android:id="@+id/lin_coin" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingTop="20dp" + android:paddingBottom="20dp" + android:gravity="center" + android:layout_weight="1"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="我的金币" + android:textSize="18sp" + android:drawableLeft="@mipmap/icon_coin" + android:drawablePadding="10dp" + android:textColor="@color/txt_normal"/> + + <TextView + android:id="@+id/txt_coin" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:textSize="25sp" + android:text="0" + android:textColor="@color/txt_normal"/> + + + </LinearLayout> + + <LinearLayout + android:id="@+id/lin_sign" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:paddingTop="20dp" + android:paddingBottom="20dp" + android:gravity="center" + android:layout_weight="1"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="连续签到" + android:textSize="18sp" + android:drawableLeft="@mipmap/sign" + android:drawablePadding="10dp" + android:textColor="@color/txt_normal"/> + + <TextView + android:id="@+id/txt_signs" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="10dp" + android:textSize="25sp" + android:text="0" + android:textColor="@color/txt_normal"/> + + + </LinearLayout> + + </LinearLayout> + + + + </LinearLayout> + <View + android:layout_width="match_parent" + android:layout_height="0.5dp" + android:background="@color/color_gray8" /> + + </LinearLayout> + </ScrollView> + + +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_notifications.xml b/app/src/main/res/layout/fragment_notifications.xml deleted file mode 100644 index 448150a..0000000 --- a/app/src/main/res/layout/fragment_notifications.xml +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout - 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" - android:layout_width="match_parent" - android:layout_height="match_parent" - tools:context=".ui.main.notifications.NotificationsFragment" > - - <TextView - android:id="@+id/text_notifications" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="8dp" - android:textAlignment="center" - android:textSize="20sp" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintBottom_toBottomOf="parent" /> -</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_service.xml b/app/src/main/res/layout/fragment_service.xml new file mode 100644 index 0000000..811fd79 --- /dev/null +++ b/app/src/main/res/layout/fragment_service.xml @@ -0,0 +1,126 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:background="@color/white" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + tools:ignore="MissingDefaultResource"> + + <View + android:layout_width="match_parent" + android:layout_height="0.5dp" + android:background="@color/cut_off_line" /> + <ScrollView + android:layout_width="match_parent" + android:layout_height="match_parent"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="20dp" + android:orientation="vertical"> + + <RelativeLayout + android:id="@+id/lin_uav" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="1dp" + android:layout_margin="10dp" + android:gravity="center_vertical"> + + <com.runt.open.mvvm.widgets.CornerImageView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:adjustViewBounds="true" + android:src="@mipmap/bg_uav" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="@color/white" + android:textSize="20sp" + android:textStyle="bold" + android:layout_marginTop="15dp" + android:layout_marginLeft="15dp" + android:text="无人机喷洒农药/化肥" /> + + + </RelativeLayout> + + <RelativeLayout + android:id="@+id/lin_yumi" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="1dp" + android:layout_margin="10dp" + android:gravity="center_vertical"> + + <com.runt.open.mvvm.widgets.CornerImageView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:adjustViewBounds="true" + android:src="@mipmap/bg_yumi" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="@color/white" + android:textSize="20sp" + android:textStyle="bold" + android:layout_marginTop="15dp" + android:layout_marginLeft="15dp" + android:text="玉米收割" /> + + + </RelativeLayout> + <RelativeLayout + android:id="@+id/lin_bozhong" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="1dp" + android:layout_margin="10dp" + android:gravity="center_vertical"> + + <com.runt.open.mvvm.widgets.CornerImageView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:adjustViewBounds="true" + android:src="@mipmap/bg_bozhong" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="@color/white" + android:textSize="20sp" + android:textStyle="bold" + android:layout_marginTop="15dp" + android:layout_marginLeft="15dp" + android:text="播种/施肥" /> + </RelativeLayout> + <RelativeLayout + android:id="@+id/lin_xiaomai" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:padding="1dp" + android:layout_margin="10dp" + android:gravity="center_vertical"> + + <com.runt.open.mvvm.widgets.CornerImageView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:adjustViewBounds="true" + android:src="@mipmap/bg_xiaomai" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textColor="@color/white" + android:textSize="20sp" + android:textStyle="bold" + android:layout_marginTop="15dp" + android:layout_marginLeft="15dp" + android:text="小麦收割" /> + </RelativeLayout> + </LinearLayout> + </ScrollView> +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/item_msg.xml b/app/src/main/res/layout/item_msg.xml new file mode 100644 index 0000000..96d8fc7 --- /dev/null +++ b/app/src/main/res/layout/item_msg.xml @@ -0,0 +1,66 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center" + android:orientation="vertical" > + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:paddingTop="20dp" + android:paddingBottom="20dp" + android:paddingLeft="@dimen/default_margin_lr" + android:paddingRight="@dimen/default_margin_lr" + android:background="@drawable/bg_white" + android:gravity="center" + android:orientation="vertical" > + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="horizontal" + android:gravity="bottom" > + + <TextView + android:id="@+id/txt_title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:textStyle="bold" + android:textSize="@dimen/title_size" + android:text="挖鼻通知" /> + <TextView + android:id="@+id/txt_time" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:alpha="0.6" + android:text="02-11" /> + + </LinearLayout> + + <androidx.appcompat.widget.AppCompatTextView + android:id="@+id/txt_detail" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="5dp" + android:alpha="0.6" + android:text="l;ajs;ldjf;ljas;ldfjasdfasdfasdfasdf很垃圾乐山大佛了计算的;了时代峻峰拉三等奖了可接受的来精神的分了就l;asjdflkjl;asjdf;lkajsdf" + android:singleLine="true"/> + + + + </LinearLayout> + <View + android:layout_width="match_parent" + android:layout_height="0.5dp" + android:background="@color/cut_off_line" /> + <LinearLayout + android:id="@+id/lin_ad" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="wrap_content" ></LinearLayout> + + +</LinearLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/refresh_recycler.xml b/app/src/main/res/layout/refresh_recycler.xml index fceabe9..f7b6d8e 100644 --- a/app/src/main/res/layout/refresh_recycler.xml +++ b/app/src/main/res/layout/refresh_recycler.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <com.scwang.smart.refresh.layout.SmartRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/smart_refresh" + android:id="@+id/refresh" android:layout_width="match_parent" android:layout_height="match_parent"> diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml deleted file mode 100644 index 97a20ea..0000000 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<navigation 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" - android:id="@+id/mobile_navigation" - app:startDestination="@+id/navigation_home"> - - <fragment - android:id="@+id/navigation_home" - android:name="com.runt.open.mvvm.ui.main.home.HomeFragment" - android:label="@string/title_home" - tools:layout="@layout/fragment_home" /> - - <fragment - android:id="@+id/navigation_dashboard" - android:name="com.runt.open.mvvm.ui.main.dashboard.DashboardFragment" - android:label="@string/title_dashboard" - tools:layout="@layout/fragment_dashboard" /> - - <fragment - android:id="@+id/navigation_notifications" - android:name="com.runt.open.mvvm.ui.main.notifications.NotificationsFragment" - android:label="@string/title_notifications" - tools:layout="@layout/fragment_notifications" /> -</navigation> \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 4884702..6bab23f 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -11,6 +11,8 @@ <attr name="rightText" format="string" /> <attr name="rightTextSize" format="dimension" /> <attr name="rightTextColor" format="color" /> + <attr name="leftTint" format="color" /> + <attr name="rightTint" format="color" /> </declare-styleable> @@ -77,6 +79,31 @@ </style> + <style name="user_txt_left"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:textSize">18sp</item> + <item name="android:textColor">@color/txt_enable</item> + <item name="android:drawablePadding">10dp</item> + <item name="android:layout_marginRight">10dp</item> + </style> + <style name="tip_txt_style"> + <item name="android:layout_width">match_parent</item> + <item name="android:layout_height">@dimen/title_height</item> + <item name="android:onClick">onTypeClick</item> + <item name="android:textSize">16sp</item> + <item name="android:textColor">@color/txt_normal</item> + <item name="android:drawableRight">@drawable/check_selector</item> + <item name="android:gravity">center_vertical</item> + </style> + <style name="user_txt_value"> + <item name="android:layout_width">wrap_content</item> + <item name="android:layout_height">wrap_content</item> + <item name="android:textSize">18sp</item> + <item name="android:textColor">@color/txt_normal</item> + </style> + + <style name="btn_normal"> <item name="android:layout_width">match_parent</item> <item name="android:layout_height">wrap_content</item> -- Gitblit v1.9.1