Android Studio 从外部导入数据库并显示到页面中

Android Studio从外部导入数据库并显示到页面中

最近在开发一个单词学习的App, 准备好单词的外部数据库之后突然卡在了将数据库导入项目这一步,参考了很多网上的资料,自己动手尝试了一遍,最后成功了。在这里将我的操作过程记录一下。

1. 从外部导入数据库

首先,要导入的数据库及其内容是这样的(使用的数据库工具是SQLite Expert Professional 4.2):
在这里插入图片描述
该数据库存储在文件1.db中。

打开Android Studio,在要导入的项目中,切换至Project视图,新建一个和Java、res同级的目录assets(这个目录的位置与开发环境有关,我看网上说使用Eclispe开发环境时它在res/下,但在AS中它必须与res目录同级),然后将1.db复制到assets目录下:
在这里插入图片描述
做到这里的时候,不知道大家有没有这样的疑问:为什么要将数据库文件放在assets下?

有个解释说,这个文件夹主要用于存放应用程序中使用的外部资源文件,然后程序可以通过 I/O 流(使用AssetManager)对目录中的文件进行读写,存放在此目录下的文件都会被打包到发布包中。

接着,实现类MyDBOpenHelper.java;

这个类就是实现从assets目录读取数据库文件然后写入SD卡中,如果在SD卡中存在,就打开数据库,不存在就从assets目录下复制过去。

import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import android.database.Cursor;
import android.util.Log;


public class MyDBOpenHelper extends SQLiteOpenHelper {
    private static String PACKAGE_NAME = "com.example.wordsofmultilanguage"; //包名
    private static String DB_PATH =  "/data" + Environment.getDataDirectory().getAbsolutePath() + "/" + PACKAGE_NAME + "/databases/";
    private static String DB_NAME = "1";
    private SQLiteDatabase db;
    private final Context context;

    public MyDBOpenHelper(Context context) {
        super(context,  DB_NAME , null, 1);
        this. context  = context;
    }

    public void createDB() throws IOException {
        this.getReadableDatabase();
        try {
            copyDB();
        } catch (IOException e) {
            throw new Error("Error copying database");
        }
    }
    public void copyDB() throws IOException{
        try {
            InputStream ip =  context.getAssets().open(DB_NAME+".db");
            Log.i("Input Stream....",ip+"");
            String op=  DB_PATH  +  DB_NAME ;
            OutputStream output = new FileOutputStream( op);
            byte[] buffer = new byte[1024];
            int length;
            while ((length = ip.read(buffer))>0){
                output.write(buffer, 0, length);
                Log.i("Content.... ",length+"");
            }
            output.flush();
            output.close();
            ip.close();
        }
        catch (IOException e) {
            Log.v("error", e.toString());
        }
    }

    public void openDB() throws SQLException {
        String myPath = DB_PATH + DB_NAME;
        db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
        Log.i("open DB......",db.toString());
    }

    @Override
    public synchronized void close() {

        if(db != null)
            db.close();

        super.close();
    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

2. 显示数据库内容

在页面上显示数据库内容(即英文单词和释义)时,用到了ListView控件,新建一个 布局文件im.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
<ListView
    android:id="@+id/word_info"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
</LinearLayout>

对ListView的每一条item做布局item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/word"
        android:textSize="16dp"
        />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/mean1"
        android:textSize="16dp"
        />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/mean2"
        android:textSize="16dp"
        />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/mean3"
        android:textSize="16dp"
        />

</LinearLayout>

完成第一步外部数据库的导入之后,定义一个类initdate.java用来实例化数据库:

public class initdate {
    public String word;
    public String meaning1;
    public String meaning2;
    public String meaning3;
    public initdate(String word, String meaning1, String meaning2, String meaning3){
        this.word = word;
        this.meaning1 = meaning1;
        this.meaning2 = meaning2;
        this.meaning3 = meaning3;
    }
}

然后,实现类

package com.example.wordsofmultilanguage;

import android.content.Context;
import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.SimpleTimeZone;

import android.database.Cursor;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class test extends AppCompatActivity {
	//创建一个List对象来存储数据
    List<initdate>list = new ArrayList<>();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.im);
        ListView listView = (ListView)this.findViewById(R.id.word_info);

        MyDBOpenHelper db;
        db = new MyDBOpenHelper(this);
        try {
            db.createDB();
        } catch (IOException ioe) {
            throw new Error("Database not created....");
        }

        try {
            db.openDB();
        } catch (SQLException sqle) {
            throw sqle;
        }
        
        SQLiteDatabase db1;
        db1 = openOrCreateDatabase("1", Context.MODE_PRIVATE, null);
        Cursor c = db1.rawQuery("SELECT * FROM words1", null);

        c.moveToFirst();

        //获取表数据
        while (!c.isAfterLast()) {
            list.add(new initdate(c.getString(c.getColumnIndex("word")),c.getString(c.getColumnIndex("meaning1")),
                    c.getString(c.getColumnIndex("meaning2")),c.getString(c.getColumnIndex("meaning3"))));

            c.moveToNext();
        }
		
		//将获取到的数据通过一个循环存放到map对象中
        List<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();
        for(int i = 0; i < list.size(); i++){
            HashMap<String, Object>item = new HashMap<String, Object>();
            item.put("word", list.get(i).word);
            item.put("meaning1", list.get(i).meaning1);
            if(list.get(i).meaning2 != null){
                item.put("meaning2", list.get(i).meaning2);
            }
            //item.put("meaning2", list.get(i).meaning2);
            if(list.get(i).meaning3 != null){
                item.put("meaning2", list.get(i).meaning3);
            }
            //item.put("meaning3", list.get(i).mmeaning3);
            data.add(item);
        }
        //创建SimpleAdapter适配器将数据绑定到item显示控件上
        SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.item,
                new String[]{"word", "meaning1", "meaning2", "meaning3"}, new int[]{R.id.word, R.id.mean1, R.id.mean2, R.id.mean3});
        //实现列表的显示
        listView.setAdapter(adapter);
    }
}

效果图:
在这里插入图片描述

3. 踩坑记录

在操作过程中,导入数据库文件的时候曾经碰到以下问题:
在这里插入图片描述
我数据库使用的编码形式是UTF-8,这是我导入1.db文件后显示的内容,全是乱码,并且提示File was loaded in the wrong encoding: 'UTF-8',我的解决办法是啥也不做,不用管,只要原先的数据库内容没问题,继续往下做就可以。原因好像是因为AS打不开这个类型的文件,要用专门的SQLite工具打开,如果尝试打开的话就会变成一堆乱码,而且从此以后不管删除、重新导入多少次AS都很”贴心“地给你显示成乱码。(小白第一次用 AS 开发项目,啥也不懂,被这玩意儿坑死了,想了各种办法,最后发现它根本不影响……)

  • 13
    点赞
  • 90
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要在 Android Studio 使用 ListView 显示数据库的内容,你需要执行以下步骤: 1. 创建一个布局文件来定义 ListView 的外观和样式。 2. 在 Activity 实例化 ListView。 3. 创建一个适配器类,用于将数据库的数据绑定到 ListView 上。 4. 在 Activity 获取数据库的数据,并将其传递给适配器。 5. 将适配器设置为 ListView 的适配器。 下面是一个简单的示例: 1. 创建布局文件 list_item.xml: ```xml <?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:padding="10dp"/> ``` 2. 在 Activity 实例化 ListView: ```java ListView listView = findViewById(R.id.list_view); ``` 3. 创建适配器类 MyAdapter: ```java public class MyAdapter extends ArrayAdapter<String> { public MyAdapter(Context context, ArrayList<String> items) { super(context, 0, items); } @Override public View getView(int position, View convertView, ViewGroup parent) { String item = getItem(position); if (convertView == null) { convertView = LayoutInflater.from(getContext()).inflate(R.layout.list_item, parent, false); } TextView textView = convertView.findViewById(R.id.text_view); textView.setText(item); return convertView; } } ``` 4. 在 Activity 获取数据库的数据,并将其传递给适配器: ```java ArrayList<String> items = new ArrayList<>(); // Get data from database and add it to items ArrayList MyAdapter adapter = new MyAdapter(this, items); listView.setAdapter(adapter); ``` 5. 将适配器设置为 ListView 的适配器: ```java listView.setAdapter(adapter); ``` 这样就可以在 ListView 显示数据库的内容了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值