如何在更新 android 应用程序时用新数据库完全替换旧的 sqlite 数据库?
Posted
技术标签:
【中文标题】如何在更新 android 应用程序时用新数据库完全替换旧的 sqlite 数据库?【英文标题】:How do I completely replace the old sqlite database with new one on update of android app? 【发布时间】:2018-04-24 04:23:27 【问题描述】:我的应用程序版本 1.0 有一个 SQLite 数据库,其中包含离线数据存储。目的是用户可以在没有互联网离线的情况下搜索一些主题。现在在下一次更新中,我想将我的应用程序同步到 Web 服务,这样如果 Web 服务上更新了新主题,那么我的应用程序会自动下载它们并存储在本地 SQLite 数据库中。对于这个新场景,我需要修改旧表以及创建一些新表。但是对于旧表我只想添加一些字段并且不想丢失我的旧数据。所以现在我想,在我的下一次更新中,应用程序将删除以前的 SQLite 数据库并用这个新数据库替换。我读了this question,但被 cmets 弄糊涂了,他们正在谈论删除旧表和创建新表。但是在这种情况下,如何手动将我太多的旧数据插入新表中。
下面是我正在使用的 DBHelper 类:
public class DBHelper extends SQLiteOpenHelper
public static String DB_PATH = "/data/data/com.example.myapp/databases/";
public static String DB_NAME = "myapp.db";
public static final int DB_VERSION = 1;
public static final String TB_TOPICS = "My_Topics";
private SQLiteDatabase myDB;
private Context context;
public DBHelper(Context context)
super(context, DB_NAME, null, DB_VERSION);
this.context = context;
@Override
public void onCreate(SQLiteDatabase db)
// TODO Auto-generated method stub
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
// TODO Auto-generated method stub
@Override
public synchronized void close()
if(myDB!=null)
myDB.close();
super.close();
/***
* Open database
* @throws SQLException
*/
public void openDataBase() throws SQLException
String myPath = DB_PATH + DB_NAME;
myDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
/***
* Copy database from source code assets to device
* @throws IOException
*/
public void copyDataBase() throws IOException
try
InputStream myInput = context.getAssets().open(DB_NAME);
String outputFileName = DB_PATH + DB_NAME;
OutputStream myOutput = new FileOutputStream(outputFileName);
byte[] buffer = new byte[1024];
int length;
while((length = myInput.read(buffer))>0)
myOutput.write(buffer, 0, length);
myOutput.flush();
myOutput.close();
myInput.close();
catch (Exception e)
Log.e("tle99 - copyDatabase", e.getMessage());
/***
* Check if the database doesn't exist on device, create new one
* @throws IOException
*/
public void createDataBase() throws IOException
boolean dbExist = checkDataBase();
if (dbExist)
else
this.getReadableDatabase();
try
copyDataBase();
catch (IOException e)
Log.e("tle99 - create", e.getMessage());
// ---------------------------------------------
// PRIVATE METHODS
// ---------------------------------------------
/***
* Check if the database is exist on device or not
* @return
*/
private boolean checkDataBase()
SQLiteDatabase tempDB = null;
try
String myPath = DB_PATH + DB_NAME;
tempDB = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
catch (SQLiteException e)
Log.e("tle99 - check", e.getMessage());
if (tempDB != null)
tempDB.close();
return tempDB != null ? true : false;
下面是我从活动方法调用数据库的方法:
List<AVData> listAVData = new ArrayList<AVData>();
DBHelper dbHelper = new DBHelper(this);
try
dbHelper.createDataBase();
catch (IOException e)
e.printStackTrace();
listAVData = dbHelper.getHeadings(topicToSearch.trim());
【问题讨论】:
见SQLiteOpenHelper#onUpgrade
: 当数据库需要升级时调用。实现应使用此方法删除表、添加表或执行升级到新架构版本所需的任何其他操作。
【参考方案1】:
试试吧。
在 SQLITEOpenHelper 类中
public class YourHelperClassName extends SQLiteOpenHelper
public YourHelperClassName(Context c)
super(c, "YOUR_DBNAME", null, new_version_number);
@Override
public void onCreate(SQLiteDatabase db)
//Add the Table creation code for new version here. Since this code works for the new user or when the user cleare data from settings.
然后在其中 OverRide onUpgrade
方法并执行
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
if (oldVersion == your_old-version_number && newVersion == new_version_number)
//1.Fetch Data from old table and Assign it in a Cursor.
//2.Drop the table and Create New Table or Alter the Table.
//3.Add data to the new table from the Cursor.
// If you are Altering the table it is not required to add the data again to the table
希望这可以帮助您解决问题。使用现有数据库进行升级比创建新数据库更好。您可以使用您的逻辑进行升级。不要在升级数据库代码时将onCreate代码更改为新代码。
【讨论】:
以上是关于如何在更新 android 应用程序时用新数据库完全替换旧的 sqlite 数据库?的主要内容,如果未能解决你的问题,请参考以下文章
如何在运行时用 ChildFragmentManager 和没有 PagerSlidingTabStrip Xamarin.Android 标题的片段替换片段