左晓为主开发手持机充值管理机
zuoxiao
2025-03-14 75f59fa9a615e3584694e820ff83503e8b72ea16
refactor(generallibrary):重构网络请求模块

- 重构 ApiManager 类,优化请求流程和错误处理
- 新增 MyJsonParser 工具类,用于 JSON 解析
- 更新 RetrofitClient配置,添加日志拦截器和自定义拦截器
- 修改 SearchUserActivity,实现实际的搜索逻辑
- 新增 SearchUserBeanRequest 数据模型类feat(generallibrary): 新增通用1.0版本登录功能- 新增通用1.0版本登录界面和相关逻辑
- 实现通用1.0版本的用户搜索和列表展示功能
- 添加新的API接口和请求处理逻辑- 更新数据库路径和相关配置
17个文件已修改
4个文件已添加
440 ■■■■ 已修改文件
app/src/main/AndroidManifest.xml 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/dayu/recharge/MyApplication.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/java/com/dayu/recharge/activity/LoginActivity.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/res/layout/activity_login.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
baselibrary/src/main/java/com/dayu/baselibrary/utils/BaseCommon.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
baselibrary/src/main/java/com/dayu/baselibrary/view/LibraryDialog.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
baselibrary/src/main/res/layout/library_dialog.xml 18 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/BaseApplication.kt 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/LoginActivity.kt 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/activity/SearchUserActivity.kt 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/adapter/BaseRecycleAdapter.kt 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/adapter/SearchListAdapter.kt 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/bean/net/SearchUserResult.kt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/dao/BaseDaoSingleton.kt 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/net/ApiManager.kt 31 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/net/ApiService.kt 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/net/MyIntercepterApplication.kt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/java/com/dayu/general/net/NetConstans.kt 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
generallibrary/src/main/res/layout/item_user_list.xml 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
gradle.properties 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
qiheonlinelibrary/build.gradle 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
app/src/main/AndroidManifest.xml
@@ -41,16 +41,8 @@
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
<!--        <activity-->
<!--            android:name="com.dayu.recharge.activity.LoginActivity"-->
<!--            android:exported="true">-->
<!--            <intent-filter>-->
<!--                <action android:name="android.intent.action.MAIN" />-->
<!--                <category android:name="android.intent.category.LAUNCHER" />-->
<!--            </intent-filter>-->
<!--        </activity>-->
        <activity
            android:name="com.dayu.general.activity.MainActivity"
            android:name="com.dayu.recharge.activity.LoginActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
app/src/main/java/com/dayu/recharge/MyApplication.java
@@ -67,9 +67,14 @@
                    case BaseCommon.QHOnLineLibrary:
                        QHOnLineApplication.getInstance(this);
                        BusinessProvider.getInstance(this);
                        break;
                    case BaseCommon.Generalv1Library:
                        com.dayu.general.BaseApplication.getInstance().application = this;
                        break;
                }
            }
        } catch (Exception e) {
        } catch (
                Exception e) {
            e.printStackTrace();
            CrashReport.postCatchedException(e);
        }
app/src/main/java/com/dayu/recharge/activity/LoginActivity.java
@@ -84,6 +84,8 @@
            } else if ((passWordBean == null && psStr.equals("123456"))
                    || passWordBean != null && passWordBean.getPassWord().equalsIgnoreCase(WSMD5.getMD5Str(psStr))) {
                startToHomeActivity();
            } else if (MyApplication.myApplication.libraryType == BaseCommon.Generalv1Library) {
                com.dayu.general.activity.LoginActivity.login(nameStr, psStr, this);
            } else {
                Toast.makeText(LoginActivity.this, "密码错误", Toast.LENGTH_SHORT).show();
            }
@@ -105,7 +107,7 @@
    protected void onResume() {
        super.onResume();
        Log.i("LoginActivity", "onResume");
        if (MyApplication.myApplication.libraryType == BaseCommon.QHOnLineLibrary) {
        if (MyApplication.myApplication.libraryType == BaseCommon.QHOnLineLibrary || MyApplication.myApplication.libraryType == BaseCommon.Generalv1Library) {
            binding.nameLL.setVisibility(View.VISIBLE);
        }
    }
@@ -122,6 +124,9 @@
            } else if (type == BaseCommon.QHOnLineLibrary) {
                getQHOnlinPermission();
                binding.nameLL.setVisibility(View.VISIBLE);
            } else if (type == BaseCommon.Generalv1Library) {
                binding.nameLL.setVisibility(View.VISIBLE);
                getGeneralV1Permission();
            }
            MyApplication.myApplication.initApplication();
        });
@@ -135,6 +140,8 @@
            startActivity(new Intent(LoginActivity.this, HomeActivityQHAlone.class));
        } else if (MyApplication.myApplication.libraryType == BaseCommon.QHOnLineLibrary) {
            startActivity(new Intent(LoginActivity.this, HomeActivityQHOline.class));
        } else if (MyApplication.myApplication.libraryType == BaseCommon.Generalv1Library) {
            startActivity(new Intent(LoginActivity.this, com.dayu.general.activity.MainActivity.class));
        }
        LoginActivity.this.finish();
    }
@@ -286,6 +293,57 @@
        }
    }
    /**
     * 获取通用权限V1版本
     * 该方法用于请求应用所需的权限,以便应用可以正常运行
     */
    private void getGeneralV1Permission() {
        try {
            XXPermissions.with(this)
                    // 申请单个权限
//                    .permission(Permission.RECORD_AUDIO)
                    // 申请多个权限
                    .permission(Permission.READ_PHONE_STATE,
                            Permission.READ_EXTERNAL_STORAGE,
                            Permission.WRITE_EXTERNAL_STORAGE)
                    // 设置权限请求拦截器(局部设置)
                    //.interceptor(new PermissionInterceptor())
                    // 设置不触发错误检测机制(局部设置)
                    //.unchecked()
                    .request(new OnPermissionCallback() {
                        @Override
                        public void onGranted(@NonNull List<String> permissions, boolean allGranted) {
                            if (allGranted) {
                                if (allGranted) {//所有申请的权限都已通过
                                    try {
                                        File file = new File(com.dayu.general.dao.BaseDaoSingleton.SqlitePath);
                                        if (!file.exists()) {
                                            file.mkdirs();
                                        }
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                }
                            }
                        }
                        @Override
                        public void onDenied(@NonNull List<String> permissions, boolean doNotAskAgain) {
                            if (doNotAskAgain) {
                                // 如果是被永久拒绝就跳转到应用权限系统设置页面
                            } else {
//                                toast("获取录音和日历权限失败");
                            }
                        }
                    });
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
    long mExitTime;
    @Override
app/src/main/res/layout/activity_login.xml
@@ -45,7 +45,7 @@
                android:hint="请输入账号"
                android:maxLines="1"
                android:singleLine="true"
                android:text="zuoxiao" />
                android:text="15802220723" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
@@ -66,8 +66,7 @@
                android:layout_height="wrap_content"
                android:hint="初始密码为数字1-6"
                android:inputType="textPassword"
                android:text="ZX@@123qwA" />
                android:text="abc_123" />
        </LinearLayout>
baselibrary/src/main/java/com/dayu/baselibrary/utils/BaseCommon.java
@@ -17,6 +17,8 @@
    public final static int QHOnLineLibrary = 2;
    public final static int Generalv1Library = 3;
    /**
     * 当前卡密码错误,不是本公司卡
     */
baselibrary/src/main/java/com/dayu/baselibrary/view/LibraryDialog.java
@@ -2,6 +2,7 @@
import static android.view.Gravity.CENTER;
import static com.dayu.baselibrary.utils.BaseCommon.Generalv1Library;
import static com.dayu.baselibrary.utils.BaseCommon.HeNanLibrary;
import static com.dayu.baselibrary.utils.BaseCommon.QHAloneLibrary;
import static com.dayu.baselibrary.utils.BaseCommon.QHOnLineLibrary;
@@ -74,7 +75,12 @@
                    type = QHOnLineLibrary;
                    libraryBean.setType(type);
                    data = "确认选择齐河联网版本吗?";
                } else if (checkedId == R.id.generav1Library) {// 处理选中Option 2的逻辑
                    type = Generalv1Library;
                    libraryBean.setType(type);
                    data = "确认选择通用1.0版本吗?";
                }
            });
            TextView okBtn = findViewById(R.id.ok);
            okBtn.setOnClickListener(v -> {
baselibrary/src/main/res/layout/library_dialog.xml
@@ -19,7 +19,7 @@
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:gravity="center"
            android:text="选择版本"
            android:text="请先选择版本"
            android:textColor="@color/dialog_btn"
            android:textSize="23sp"
            android:textStyle="bold" />
@@ -79,7 +79,21 @@
                android:text="齐河单机版"
                android:textColor="@drawable/radio_text_select"
                android:textSize="20sp" />
            <RadioButton
                android:id="@+id/generav1Library"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="50dp"
                android:layout_marginTop="25dp"
                android:layout_marginRight="50dp"
                android:layout_marginBottom="5dp"
                android:background="@drawable/radio_select"
                android:button="@null"
                android:gravity="center"
                android:padding="6dp"
                android:text="通用1.0版"
                android:textColor="@drawable/radio_text_select"
                android:textSize="20sp" />
        </RadioGroup>
generallibrary/src/main/java/com/dayu/general/BaseApplication.kt
@@ -2,10 +2,25 @@
import android.app.Application
public class BaseApplication : Application() {
class BaseApplication private constructor() {
    override fun onCreate() {
        super.onCreate()
    companion object {
        @JvmField
        var application: Application? = null
        private const val TAG = "ApiManager"
        @Volatile
        private var myApplication: BaseApplication? = null
        @JvmStatic
        fun getInstance(): BaseApplication {
            return myApplication ?: synchronized(this) {
                myApplication ?: BaseApplication().also {
                    myApplication = it
                }
            }
        }
    }
}
generallibrary/src/main/java/com/dayu/general/activity/LoginActivity.kt
New file
@@ -0,0 +1,58 @@
package com.dayu.general.activity
import android.content.Context
import com.dayu.baselibrary.net.subscribers.SubscriberListener
import com.dayu.baselibrary.utils.ToastUtil
import com.dayu.general.bean.net.SearchUserResult
import com.dayu.general.net.ApiManager
import com.dayu.general.net.BaseResponse
/**
 * Description:
 * Author: zuo
 * Date: 2025/3/13
 */
class LoginActivity {
    companion object {
        @JvmStatic
        fun login(phone: String, password: String, myContext: Context) {
            val map = mutableMapOf<String, Any>()
            if (phone.isNotEmpty()) {
                map["phone"] = phone
            }
            if (password.isNotEmpty()) {
                map["password"] = password
            }
            map["orgTag"] = "ym"
            // 使用正确的类型参数
            ApiManager.getInstance().requestPostLoading(
                myContext,
                "sso/sso/loginJson",
                SearchUserResult::class.java,
                map,
                object : SubscriberListener<BaseResponse<SearchUserResult>>() {
                    override fun onNext(t: BaseResponse<SearchUserResult>) {
                        if (t.success) {
                        } else {
                            // 处理搜索失败的情况
                            ToastUtil.show(t.msg)
                        }
                    }
                    override fun onError(e: Throwable?) {
                        super.onError(e)
                        ToastUtil.show("搜索失败: ${e?.message ?: "未知错误"}")
                    }
                }
            )
        }
    }
}
generallibrary/src/main/java/com/dayu/general/activity/SearchUserActivity.kt
@@ -1,15 +1,17 @@
package com.dayu.general.activity
import android.os.Bundle
import androidx.recyclerview.widget.LinearLayoutManager
import com.dayu.baselibrary.net.subscribers.SubscriberListener
import com.dayu.baselibrary.utils.ToastUtil
import com.dayu.baselibrary.view.TitleBar.ClickType_LEFT_IMAGE
import com.dayu.baselibrary.view.TitleBar.ClickType_RIGHT_IMAGE
import com.dayu.general.adapter.SearchListAdapter
import com.dayu.general.bean.net.SearchUserResult
import com.dayu.general.databinding.ActivitySearchUserGeBinding
import com.dayu.general.dialog.SearchDialog
import com.dayu.general.net.ApiManager
import com.dayu.general.net.BaseResponse
import com.dayu.qiheonlinelibrary.net.ApiManager
/**
 * @author: zuo
@@ -19,56 +21,70 @@
class SearchUserActivity : BaseActivity() {
    var binding: ActivitySearchUserGeBinding? = null
    private var userAdapter: SearchListAdapter? = null
    var searchDialog: SearchDialog? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivitySearchUserGeBinding.inflate(layoutInflater)
        setContentView(binding?.root)
        initView()
        setupRecyclerView()
    }
    fun initView() {
        searchDialog = SearchDialog(this)
        searchDialog?.show()
        binding?.titleBar?.setOnItemclickListner(ClickType_LEFT_IMAGE) { this.finish() }
        // 设置搜索监听器
        searchDialog?.setOnSearchListener(object : SearchDialog.OnSearchListener {
            override fun onSearch(farmerId: String, farmerName: String, cardNumber: String) {
                // 处理搜索结果
                // 这里只是示例,实际应用中可能需要调用API或查询数据库
                val message =
                    "搜索条件:\n农户编号:$farmerId\n农户名称:$farmerName\n卡号:$cardNumber"
                // 执行实际的搜索逻辑
                searchUser(farmerId, farmerName, cardNumber)
            }
        })
        binding?.titleBar?.setOnItemclickListner(ClickType_RIGHT_IMAGE) {
            // 创建搜索对话框
            val searchDialog = SearchDialog(this)
            // 设置搜索监听器
            searchDialog.setOnSearchListener(object : SearchDialog.OnSearchListener {
                override fun onSearch(farmerId: String, farmerName: String, cardNumber: String) {
                    // 处理搜索结果
                    // 这里只是示例,实际应用中可能需要调用API或查询数据库
                    val message =
                        "搜索条件:\n农户编号:$farmerId\n农户名称:$farmerName\n卡号:$cardNumber"
                    // 执行实际的搜索逻辑
                    performSearch(farmerId, farmerName, cardNumber)
                }
            })
            // 显示对话框
            searchDialog.show()
            searchDialog?.show()
        }
    }
    private fun setupRecyclerView() {
        userAdapter = SearchListAdapter()
        binding?.recyclerView?.apply {
            layoutManager = LinearLayoutManager(this@SearchUserActivity)
            adapter = userAdapter
        }
    }
    /**
     * 执行搜索逻辑
     * 这里只是一个示例方法,实际应用中需要根据具体需求实现
     * 根据农民ID、姓名和银行卡号搜索用户
     *
     * 此函数构建一个参数映射,根据提供的农民ID、姓名和银行卡号来搜索用户
     * 它仅包含有效的、非空的搜索参数,以确保搜索请求的准确性和效率
     *
     * @param farmerId 农民的唯一标识符
     * @param farmerName 农民的姓名
     * @param cardNumber 银行卡号
     */
    private fun performSearch(farmerId: String, farmerName: String, cardNumber: String) {
        // 调用实际的搜索API
        searchUser(farmerId, farmerName, cardNumber)
    }
    private fun searchUser(farmerId: String, farmerName: String, cardNumber: String) {
        val map = mutableMapOf<String, String>()
        val map = mutableMapOf<String, Any>()
        if (farmerId.isNotEmpty()) {
            map["farmerId"] = farmerId
        }
        if (farmerName.isNotEmpty()) {
            map["farmerName"] = farmerName
        }
        if (cardNumber.isNotEmpty()) {
            map["cardNumber"] = cardNumber
        }
@@ -76,7 +92,7 @@
        // 使用正确的类型参数
        ApiManager.getInstance().requestGetLoading(
            this,
            "searchUser",
            "sell/client/get",
            SearchUserResult::class.java,
            map,
            object : SubscriberListener<BaseResponse<SearchUserResult>>() {
@@ -86,7 +102,11 @@
                        val result = t.content
                        if (result != null) {
                            // 处理搜索结果
                            handleSearchResult(result)
                            if (result.obj.isNotEmpty()) {
                                userAdapter?.setData(result.obj)
                            } else {
                                ToastUtil.show("未找到匹配的用户")
                            }
                        } else {
                            ToastUtil.show("未找到匹配的用户")
                        }
@@ -95,7 +115,7 @@
                        ToastUtil.show(t.msg)
                    }
                }
                override fun onError(e: Throwable?) {
                    super.onError(e)
                    ToastUtil.show("搜索失败: ${e?.message ?: "未知错误"}")
@@ -103,14 +123,9 @@
            }
        )
    }
    /**
     * 处理搜索结果
     */
    private fun handleSearchResult(result: SearchUserResult) {
        // 在这里实现搜索结果的处理逻辑
        // 例如:更新UI显示搜索结果列表
        // 或者跳转到结果详情页面
    }
}
}
generallibrary/src/main/java/com/dayu/general/adapter/BaseRecycleAdapter.kt
New file
@@ -0,0 +1,43 @@
package com.dayu.general.adapter
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.dayu.baselibrary.databinding.ItemNoMoreBinding
/**
 * Description:
 * Author: zuo
 * Date: 2025/3/10
 */
class BaseRecycleAdapter<T : RecyclerView.ViewHolder>:RecyclerView.Adapter<T>() {
    companion object {
        const val VIEW_TYPE_ITEM = 1
        const val VIEW_TYPE_EMPTY = 0
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): T {
        TODO("Not yet implemented")
    }
    override fun getItemCount(): Int {
        TODO("Not yet implemented")
    }
    override fun onBindViewHolder(holder: T, position: Int) {
        TODO("Not yet implemented")
    }
    class ViewHolderEmpty(binding: ItemNoMoreBinding) : RecyclerView.ViewHolder(binding.root) {
        var mBinding: ItemNoMoreBinding = binding
        fun getBinding(): ItemNoMoreBinding {
            return mBinding
        }
        fun setBinding(binding: ItemNoMoreBinding) {
            this.mBinding = binding
        }
    }
    }
generallibrary/src/main/java/com/dayu/general/adapter/SearchListAdapter.kt
New file
@@ -0,0 +1,49 @@
package com.dayu.general.adapter
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.dayu.general.bean.net.SearchUserResult
import com.dayu.general.databinding.ItemUserListBinding
/**
 * Description:
 * Author: zuo
 * Date: 2025/3/10
 */
class SearchListAdapter :  RecyclerView.Adapter<SearchListAdapter.UserViewHolder>(){
    private val userList = mutableListOf<SearchUserResult.UserInfo>()
    fun setData(users: List<SearchUserResult.UserInfo>) {
        userList.clear()
        userList.addAll(users)
        notifyDataSetChanged()
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
        val binding = ItemUserListBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return UserViewHolder(binding)
    }
    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        val user = userList[position]
        holder.bind(user)
    }
    override fun getItemCount(): Int = userList.size
    inner class UserViewHolder(private val binding: ItemUserListBinding) : RecyclerView.ViewHolder(binding.root) {
        fun bind(user: SearchUserResult.UserInfo) {
            binding.tvCardCount.text = "卡数量:${user.cardCount ?: "0"}"
            binding.tvFarmerId.text = "客户编号:${user.clientNum ?: ""}"
            binding.tvIdCard.text = "身份证:${user.idCard ?: ""}"
            binding.tvName.text = "姓名:${user.name ?: ""}"
            binding.tvPhone.text = "电话:${user.phone ?: ""}"
            binding.root.setOnClickListener {
                // 可以在此处添加点击事件,例如查看用户详情
            }
        }
    }
}
generallibrary/src/main/java/com/dayu/general/bean/net/SearchUserResult.kt
@@ -19,7 +19,7 @@
        val address: String? = null,   // 地址
        val cardCount: Int? = null,    // 卡数量
        val clientNum: String? = null, // 客户编号
        val id: Int? = null,           // ID
        val id: String? = null,           // ID
        val idCard: String? = null,    // 身份证
        val name: String? = null,      // 姓名
        val operateDt: String? = null, // 操作日期
generallibrary/src/main/java/com/dayu/general/dao/BaseDaoSingleton.kt
@@ -8,12 +8,17 @@
class BaseDaoSingleton {
    companion object {
        @JvmField
        val SqlitePath: String =
            Environment.getExternalStorageDirectory().absolutePath + File.separator + ".dayu" + File.separator + "data" + File.separator
    }
    var baseDao: AppDataBase? = null
    var AsynchBaseDao: AppDataBase? = null
    var SqlitePath: String =
        Environment.getExternalStorageDirectory().absolutePath + File.separator + ".dayu" + File.separator + "data" + File.separator
    //MyFileUtil.SqlitePath +
    fun getInstance(context: Context?): AppDataBase? {
generallibrary/src/main/java/com/dayu/general/net/ApiManager.kt
@@ -1,14 +1,9 @@
package com.dayu.qiheonlinelibrary.net
package com.dayu.general.net
import android.content.Context
import android.util.Log
import com.dayu.baselibrary.net.subscribers.ProgressSubscriber
import com.dayu.baselibrary.net.subscribers.SubscriberListener
import com.dayu.general.net.ApiService
import com.dayu.general.net.BaseResponse
import com.dayu.general.net.MyJsonParser
import com.dayu.general.net.NetConstans
import com.dayu.general.net.RetrofitClient
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.functions.Function
import io.reactivex.rxjava3.schedulers.Schedulers
@@ -27,18 +22,10 @@
        @Volatile
        private var apiManager: ApiManager? = null
        fun init() {
            if (apiManager == null) {
                synchronized(ApiManager::class) {
                    if (apiManager == null) {
                        apiManager = ApiManager()
                    }
                }
            }
        }
        fun getInstance(): ApiManager {
            return apiManager ?: throw IllegalStateException("ApiManager not initialized")
            return apiManager ?: synchronized(this) {
                apiManager ?: ApiManager().also { apiManager = it }
            }
        }
    }
@@ -132,11 +119,11 @@
        val mySubscriber = ProgressSubscriber<BaseResponse<T>>(context, hideLoading, listener);
        observable
            ?.subscribeOn(Schedulers.io())
            ?.map(mapResponse(tClass))
            ?.unsubscribeOn(Schedulers.newThread())
            ?.observeOn(AndroidSchedulers.mainThread())
            ?.subscribe(mySubscriber)
            .subscribeOn(Schedulers.io())
            .map(mapResponse(tClass))
            .unsubscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(mySubscriber)
    }
    private fun <T> mapResponse(tClass: Class<T>): Function<Any, BaseResponse<T>> {
generallibrary/src/main/java/com/dayu/general/net/ApiService.kt
@@ -14,19 +14,19 @@
    @POST
    fun requestPost(
        @Url url: String,
        @Body params: Map<String, Any?>?
    ): Observable<BaseResponse<Any?>>?
        @Body params: Map<String, @JvmSuppressWildcards Any>
    ): Observable<BaseResponse<Any>>
    @POST
    fun requestPost(@Url url: String?): Observable<BaseResponse<Any?>>?
    fun requestPost(@Url url: String): Observable<BaseResponse<Any>>
    @GET("{url}")
    fun requestGet(
        @Path("url") url: String,
        @QueryMap params: Map<String, Any?>?
    ): Observable<BaseResponse<Any?>>?
        @QueryMap params: Map<String, @JvmSuppressWildcards Any>
    ): Observable<BaseResponse<Any>>
    @GET("{url}")
    fun requestGet(@Path("url") url: String): Observable<BaseResponse<Any?>>?
    fun requestGet(@Path("url") url: String): Observable<BaseResponse<Any>>
}
generallibrary/src/main/java/com/dayu/general/net/MyIntercepterApplication.kt
@@ -44,6 +44,7 @@
            val params: Map<*, *> = HashMap<Any?, Any?>()
            if (request.method == "GET") {
                builder.url(request.url.toString())
            } else {
            }
generallibrary/src/main/java/com/dayu/general/net/NetConstans.kt
@@ -7,7 +7,7 @@
 */
class NetConstans {
    companion object {
        const val BASE_URL: String = "http://120.46.45.35:20081/api/sjgg/"
        const val BASE_URL: String = "https://no253541tf71.vicp.fun/"
        const val TOKEN_INVALID: String = "0000"
    }
generallibrary/src/main/res/layout/item_user_list.xml
New file
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="12dp">
    <TextView android:id="@+id/tvCardCount" android:layout_width="match_parent" android:layout_height="wrap_content" />
    <TextView android:id="@+id/tvFarmerId" android:layout_width="match_parent" android:layout_height="wrap_content" />
    <TextView android:id="@+id/tvIdCard" android:layout_width="match_parent" android:layout_height="wrap_content" />
    <TextView android:id="@+id/tvName" android:layout_width="match_parent" android:layout_height="wrap_content" />
    <TextView android:id="@+id/tvPhone" android:layout_width="match_parent" android:layout_height="wrap_content" />
</LinearLayout>
gradle.properties
@@ -15,3 +15,5 @@
android.nonTransitiveRClass=true
android.useAndroidX=true
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding\=UTF-8
# 指定使用Java 11
org.gradle.java.home=C:\\Program Files\\Java\\jdk-11
qiheonlinelibrary/build.gradle
@@ -82,7 +82,7 @@
    compileOnly 'androidx.recyclerview:recyclerview:1.2.0'//经典刷新头
    //将注释掉的远程依赖改为本地aar引用
    implementation files('../baselibrary/libs/avi.library-2.1.3.aar')
    compileOnly files('../baselibrary/libs/avi.library-2.1.3.aar')
    compileOnly group: 'net.sourceforge.jexcelapi', name: 'jxl', version: '2.6.12'
}