Android 读取SD卡SQLite文件

        今天心情有些不爽, 原来之前内存溢出的原因不是手机硬件的问题, 是我代码写的有问题==

        开始模拟的场景是这样的==  连后台取大JSON串,解析-转成相应对象-存入数据库; 由于后台暂时没有数据,所以只能自己模拟测试数据; 那么我的策略是这样的: 连续new出来目标数据的对象数放置到一个list中,然后再将这个list异步插入到数据库中;看似没有问题, 但是一直以来我都忽略了一个非常重要的问题,大数据! 万一有300W条记录呢? 你要new300W个对象吗? 开玩笑······· 所以这几天难为我的小米2了,一直认为它不给力, 不到100W就内存溢出·· 现在想起来, 其实已经很够给力的了;

这300W个对象的内存占用可不是闹着玩的··········· 所以我只能换种思路;

        1. 我不通过new对象的形式向数据库中插入对象,反正我最终要的是模拟数据, 我直接用db.exel();循环向里面插入数据不也是一样的吗? 这样一来那300W个对象不就可以不用创建了吗? 为什么自己没早些考虑这方面的问题、 经验教训呐

        2. 今天去咨询了兄弟开发IOS那边, 给了我几个比较有参考性的意见:

            可以将每次提交的记录数减少==少量多次, 将300W条记录每1000条记录提交一次; 那么就可以缓解写入的数据库压力;

            看看模拟的对象占用的内存是否已经将栈空间填满, 其实我考虑到运行时内存这个概念了,但是水平不够,没能往下思考;

            在线解析JSON大字符串这个策略是不科学的,一方面耗时,其二万一中途网络中断,要考虑到断点续传?所以只能剩下其中2中方式可行:1,第一次安装的时候就先带一个数据库文件放置SD卡上,用程序读这个SD卡内容;或者在线下载一个压缩包,本地解压,然后在读;2,当后续有增量数据产生时,如果数据量小,可以采用在线解析JSON然后添加到数据库中; 如果数据量较大,考虑分批获取数据=少量多次请求数据; 如果间隔时间的确较长,参考后台给的数据压缩规则, 实在不行就重新获取新数据包,覆盖之前的数据;

        3. 考虑了下, 我还是要模拟下从程序中读取sd卡中的数据库文件比较靠谱;用可视化工具做了个简单的数据库文件, 然后copy到SD卡中,开始模拟读取;

         按照惯例, 先爆几张过程图看看流程==通过SQLite Developer可视化工具生成DB文件:

  

  

 数据库文件已经拷贝到SD卡根目录下===

运行效果== 此处我只是做了查询处理,添加功能暂时未做,可根据上图结构自行添加:

      

       说说以下测试程序的构成:

     1. 傻瓜式布局;

     2.从外界获取的数据库文件存放至SD卡的根目录;

     3.manifest文件添加读写权限;

     4.写一个openHelper数据库操作帮助类;

     5.按照数据库表结构建立相应的实体类(entity  or   bean);

     6.activity的数据展现;

【布局】

<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="match_parent" 
    android:orientation="vertical">

	<EditText android:id="@+id/input"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:hint="请输入要插入的数据"/>
	<EditText android:id="@+id/input_detail"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:hint="输入数据的详细信息"/>
	
	<Button android:id="@+id/addBtn"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:text="点击添加"/>
	
	<EditText android:id="@+id/showContext"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:hint="显示查询数据"/>
	<Button android:id="@+id/searchBtn"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:text="点击查询"/>

	<TextView
	    android:id="@+id/show_textview"
	    android:layout_width="match_parent"
	    android:layout_height="wrap_content"
	    android:text="TextView" />
    
</LinearLayout>

  【权限】

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>

【openHelper帮助类】

package com.example.test_sqlite;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.example.test_sqlite.entity.MainData;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class MyDBHelper extends SQLiteOpenHelper{
	//数据库文件在SD卡中,此时必须用全限定名!! 默认路径在/data/data/databases/testDBinSD.sqlite, 但私密数据外界看不到-除非root。
	private static final String SQL_NAME = "/sdcard/testDBinSD.sqlite";//数据库名称。//Environment.getExternalStorageDirectory().getPath() + "testDBinSD.sqlite";//
	private static final String MAIN_DATA_TABLE_NAME = "maindata";//表名。
	private static final String MAIN_DATA_ID = "id";//表的4个字段
	private static final String MAIN_DATA_NAME = "name";
	private static final String MAIN_DATA_SEX = "sex";
	private static final String MAIN_DATA_GRADE = "grade";
	
	//构造方法
	public MyDBHelper(Context context) {
		super(context, SQL_NAME, null, 1);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		//建表
		String mainDataSQL = "create table if not exists " + MAIN_DATA_TABLE_NAME + "("
				+ MAIN_DATA_ID + " varchar(20), "
				+ MAIN_DATA_NAME + " varchar(20), "
				+ MAIN_DATA_SEX + " varchar(20), "
				+ MAIN_DATA_GRADE + " varchar(20));";
		db.execSQL(mainDataSQL);
	}

	//读文件获取记录。
	public List<MainData> getMainData() {
		String mainDataSQL = "select * from "+MAIN_DATA_TABLE_NAME+"";
		File name = new File(SQL_NAME);
		SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(name, null);//读SD卡数据库必须如此--用静态方法打开数据库。
		Cursor cursor = db.rawQuery(mainDataSQL, null);	
		List<MainData> dataList = new ArrayList<MainData>();
		if (cursor != null) { 
			while (cursor.moveToNext()) {//直到返回false说明表中到了数据末尾
				MainData data = new MainData();
				data.setId(cursor.getString(0));
				data.setName(cursor.getString(1));
				data.setSex(cursor.getString(2));
				data.setGrade(cursor.getString(3));
				dataList.add(data);
			}
		}
		cursor.close();
		db.close();
		
		return dataList;
	}
	
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		
	}

}

 【实体类】

package com.example.test_sqlite.entity;

public class MainData {

	private String id;
	private String name;
	private String sex;
	private String grade;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getGrade() {
		return grade;
	}
	public void setGrade(String grade) {
		this.grade = grade;
	}
}

【activity数据查询-展现】

package com.example.test_sqlite;

import java.util.List;
import com.example.test_sqlite.entity.MainData;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.app.Activity;

public class MainActivity extends Activity implements OnClickListener {

	private MyDBHelper dbHelper;//SQLite帮助类
	
	private EditText input;
	private EditText inputDetail;
	private Button addBtn;
	private EditText showContent;
	//最主要功能是下面的俩=== 点击查询--数据呈现。
	private Button searchBtn;
	private TextView showText;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		dbHelper = new MyDBHelper(this);
		
		input = (EditText) findViewById(R.id.input);
		inputDetail = (EditText) findViewById(R.id.input_detail);
		addBtn = (Button) findViewById(R.id.addBtn);
		showContent = (EditText) findViewById(R.id.showContext);
		searchBtn = (Button) findViewById(R.id.searchBtn);
		showText = (TextView) findViewById(R.id.show_textview);
		
		addBtn.setOnClickListener(this);
		searchBtn.setOnClickListener(this);
	}

	@Override
	public void onClick(View v) {
		if(v.getId() == R.id.addBtn) {
//			handleInsertDB();
		} else if(v.getId() == R.id.searchBtn) {
			handleSearchDB();
		}
	}

	private void handleSearchDB() {
		//查询sql。返回记录集合。
		List<MainData> dataList = dbHelper.getMainData();
		StringBuilder sb = new StringBuilder();
		for(MainData data : dataList) {
			sb.append(data.getId()).append("-").//循环将记录拼接起来方便显示。
					append(data.getName()).append("-").append(data.getSex()).
					append("-").append(data.getGrade()).append("-\n").toString();
		}
		showText.setText(sb);//显示结果。
	}

	private void handleInsertDB() {

	}
}

       说明从SD卡中读取SQLite文件是可以实现的============

       那么同事给我的那些建议是可行的, 明天去公司试试, 哦不对, 今上午~

       要睡觉了, 已经吵着基友睡觉了·························为了写博客,影响不少人啊、

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值