You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中如何将SQL Server返回的ArrayList存入SQLite并绑定自定义ListView

实现方案

你当前代码最大的问题是把每行记录的8个字段零散存入ArrayList,既无法按行区分数据,也没法对接后续的数据库插入和列表绑定,按以下步骤改即可:

1. 新建数据实体类

新建TaggedItem.java,用来按行结构化存储存储过程返回的数据:

package com.example.storedprocedures;

public class TaggedItem {
    private String mrCode;
    private String docIdBranch;
    private String brchName;
    private String industryType;
    private String specializationId;
    private String uName;
    private String classId;
    private String maxVisit;

    public TaggedItem() {}

    // 全字段构造、get/set方法可以用Android Studio自动生成,这里列核心方法
    public String getMrCode() { return mrCode; }
    public void setMrCode(String mrCode) { this.mrCode = mrCode; }
    public String getDocIdBranch() { return docIdBranch; }
    public void setDocIdBranch(String docIdBranch) { this.docIdBranch = docIdBranch; }
    public String getBrchName() { return brchName; }
    public void setBrchName(String brchName) { this.brchName = brchName; }
    public String getIndustryType() { return industryType; }
    public void setIndustryType(String industryType) { this.industryType = industryType; }
    public String getSpecializationId() { return specializationId; }
    public void setSpecializationId(String specializationId) { this.specializationId = specializationId; }
    public String getuName() { return uName; }
    public void setuName(String uName) { this.uName = uName; }
    public String getClassId() { return classId; }
    public void setClassId(String classId) { this.classId = classId; }
    public String getMaxVisit() { return maxVisit; }
    public void setMaxVisit(String maxVisit) { this.maxVisit = maxVisit; }
}

2. 实现SQLite批量插入逻辑

新建SQLiteHelper.java,用SQLite事务做批量插入,性能比循环单条插入高10倍以上:

package com.example.storedprocedures;

import android.content.ContentValues;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.List;

public class SQLiteHelper extends SQLiteOpenHelper {
    private static final String DB_NAME = "local_biz.db";
    private static final int DB_VERSION = 1;
    private static final String TABLE_TAGGED = "tagged_list";

    public SQLiteHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String createTable = "CREATE TABLE IF NOT EXISTS " + TABLE_TAGGED + "(" +
                "id INTEGER PRIMARY KEY AUTOINCREMENT," +
                "mrCode TEXT," +
                "docId_branch TEXT," +
                "brchName TEXT," +
                "industry_type TEXT," +
                "specialization_id TEXT," +
                "uName TEXT," +
                "class_id TEXT," +
                "max_visit TEXT)";
        db.execSQL(createTable);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " + TABLE_TAGGED);
        onCreate(db);
    }

    public void batchSaveTaggedList(List<TaggedItem> dataList) {
        SQLiteDatabase db = getWritableDatabase();
        db.beginTransaction();
        try {
            // 不需要保留旧数据就先清空,根据业务需求调整
            db.delete(TABLE_TAGGED, null, null);
            ContentValues cv = new ContentValues();
            for (TaggedItem item : dataList) {
                cv.clear();
                cv.put("mrCode", item.getMrCode());
                cv.put("docId_branch", item.getDocIdBranch());
                cv.put("brchName", item.getBrchName());
                cv.put("industry_type", item.getIndustryType());
                cv.put("specialization_id", item.getSpecializationId());
                cv.put("uName", item.getuName());
                cv.put("class_id", item.getClassId());
                cv.put("max_visit", item.getMaxVisit());
                db.insert(TABLE_TAGGED, null, cv);
            }
            db.setTransactionSuccessful();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            db.endTransaction();
            db.close();
        }
    }
}

3. 实现自定义ListView

首先新建列表项布局res/layout/item_tagged.xml,按需加要展示的字段控件:

<?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"
    android:background="?attr/selectableItemBackground">

    <TextView
        android:id="@+id/tv_mrcode"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textStyle="bold"/>

    <TextView
        android:id="@+id/tv_brch"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:layout_marginTop="4dp"/>

    <TextView
        android:id="@+id/tv_user"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:layout_marginTop="2dp"/>
</LinearLayout>

新建自定义适配器TaggedListAdapter.java,替换原生ArrayAdapter:

package com.example.storedprocedures;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;

public class TaggedListAdapter extends BaseAdapter {
    private Context context;
    private List<TaggedItem> dataList;

    public TaggedListAdapter(Context context, List<TaggedItem> dataList) {
        this.context = context;
        this.dataList = dataList;
    }

    @Override
    public int getCount() { return dataList.size(); }
    @Override
    public Object getItem(int position) { return dataList.get(position); }
    @Override
    public long getItemId(int position) { return position; }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(context).inflate(R.layout.item_tagged, parent, false);
            holder = new ViewHolder();
            holder.tvMrCode = convertView.findViewById(R.id.tv_mrcode);
            holder.tvBrch = convertView.findViewById(R.id.tv_brch);
            holder.tvUser = convertView.findViewById(R.id.tv_user);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        TaggedItem item = dataList.get(position);
        holder.tvMrCode.setText("MR编码:" + item.getMrCode());
        holder.tvBrch.setText("所属网点:" + item.getBrchName());
        holder.tvUser.setText("负责人:" + item.getuName());
        return convertView;
    }

    static class ViewHolder {
        TextView tvMrCode;
        TextView tvBrch;
        TextView tvUser;
    }
}

4. 修改MainActivity逻辑

把原来两个按钮点击事件里的零散取值逻辑替换成结构化存储、插库、绑列表的流程,以查询全部的按钮为例:

btnviewall.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        try {
            PreparedStatement statement = connect.prepareStatement("EXEC SP_TaggedList");
            ArrayList<TaggedItem> list = new ArrayList<>();
            rs = statement.executeQuery();
            while (rs.next()) {
                TaggedItem item = new TaggedItem();
                item.setMrCode(rs.getString("mrCode"));
                item.setDocIdBranch(rs.getString("docId_branch"));
                item.setBrchName(rs.getString("brchName"));
                item.setIndustryType(rs.getString("industry_type"));
                item.setSpecializationId(rs.getString("specialization_id"));
                item.setuName(rs.getString("uName"));
                item.setClassId(rs.getString("class_id"));
                item.setMaxVisit(rs.getString("max_visit"));
                list.add(item);
            }
            // 批量存SQLite
            new SQLiteHelper(MainActivity.this).batchSaveTaggedList(list);
            // 绑定数据到自定义列表
            TaggedListAdapter adapter = new TaggedListAdapter(MainActivity.this, list);
            lstTaggedList.setAdapter(adapter);

            // 关闭资源
            rs.close();
            statement.close();
        } catch (SQLException e) {
            Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }
});

按ID查询的按钮逻辑完全一致,注意不要用字符串拼接SQL,避免注入风险,改成参数占位符写法:

PreparedStatement statement = connect.prepareStatement("EXEC SP_TaggedList ?");
statement.setString(1, edtid.getText().toString());

列表点击事件同步修改,直接取实体对象即可:

lstTaggedList.setOnItemClickListener((parent, view, position, id) -> {
    TaggedItem selected = (TaggedItem) parent.getItemAtPosition(position);
    Toast.makeText(MainActivity.this, "选中:" + selected.getMrCode(), Toast.LENGTH_LONG).show();
});

注意事项

  • 你当前用StrictMode绕过主线程网络请求限制的写法仅适合调试,正式环境必须把SQL Server连接、查询逻辑放到子线程执行,否则网络稍慢就会ANR闪退,查询完成后再切回主线程更新UI
  • 数据库连接、ResultSet、PreparedStatement用完必须关闭,否则会出现内存泄漏
  • 列表项布局可以按需增减字段,只要在适配器的getView方法里对应赋值即可

内容的提问来源于stack exchange,提问作者Ryan Baltazar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 13:06:08