【问题标题】:Can't write to preloaded database using SQLite Asset Helper无法使用 SQLite Asset Helper 写入预加载的数据库
【发布时间】:2017-11-29 02:26:56
【问题描述】:

我正在使用 SQLite Asset Helper 访问预加载的数据库。我可以成功读取它(getAllAuthors() 方法按预期工作),但我无法写入它。

Log.i("insert", insertQuery)Log.i("select", selectQuery) 按预期返回,执行insertQueryselectQuery 时没有错误。但是当我在外部 DB Browser for SQLite 应用程序中打开我的数据库时,数据库没有任何变化。

数据库助手

public class DatabaseHelper extends SQLiteAssetHelper {

    private static final int DATABASE_VERSION = 1;

    private static final String DATABASE_NAME = "database9.db";
    private static final String BOOKS = "books";
    private static final String AUTHORS = "authors";

    public DatabaseHelper (Context context) {
        super(context, DATABASE_NAME, null, DATABASE_VERSION);
    }

    // THIS WORKS FINE
    public ArrayList<Author> getAllAuthors() {

        ArrayList<Author> authorList = new ArrayList<>();

        // Select all query
        String selectQuery = "SELECT id, name FROM " + AUTHORS + " ORDER BY name_alphabetic";

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                // create new author object
                Author author = new Author();
                // set ID and name of author object
                author.setID(Integer.parseInt(cursor.getString(0)));
                author.setName(cursor.getString(1));
                // pass author object to authorList array
                authorList.add(author);
            } while (cursor.moveToNext());
        }

        // return author list
        return authorList;
    }

    public int setScrollPosition(int scrollY, int storyID) {

        String insertQuery = "UPDATE " + BOOKS + " SET scroll_position = " + scrollY + " WHERE id = " + storyID;
        Log.i("insert", insertQuery);
        SQLiteDatabase db = this.getWritableDatabase();
        db.execSQL(insertQuery);

        return scrollY;

    }

    public int getScrollPosition(int storyID) {

        int scrollPosition = 0;

        String selectQuery = "SELECT scroll_position FROM " + BOOKS + " WHERE id = " + storyID;
        Log.i("select", selectQuery);

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) {
            do {
                scrollPosition = cursor.getInt(0);
            } while (cursor.moveToNext());
        }

        return scrollPosition;

    }

}

StoryBodyActivity

public class StoryBodyActivity extends AppCompatActivity {

    private TextView storyBodyTextView;
    private ScrollView storyBodyScrollView;
    public int storyID;
    Parcelable state;
    int scrollY;

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_story_body, menu);
        return true;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_story_body);

        Bundle extras = getIntent().getExtras();

        String story = extras.getString("story");
        storyID = extras.getInt("story_id");
        Log.i("stories", Integer.toString(storyID));

        storyBodyTextView = (TextView) findViewById(R.id.story_body_text_view);
        storyBodyScrollView = (ScrollView) findViewById(R.id.story_body_scroll_view);

        DatabaseHelper db = new DatabaseHelper(this);
        scrollY = db.getScrollPosition(storyID);
        Log.i("scrolly", Integer.toString(scrollY));

        storyBodyScrollView.scrollTo(0, scrollY);

        String storyBody = db.getStoryBody(storyID);

        storyBodyTextView.setText(Html.fromHtml(storyBody));

        if(state != null) {
            Log.d("pause", "trying to restore textview state..");
            storyBodyTextView.onRestoreInstanceState(state);
        }

        int scroll = storyBodyScrollView.getScrollY();
        Log.i("onCreate scroll", Integer.toString(scroll));

    }

    @Override
    public void onPause() {
        // Log.d("pause", "saving listview state @ onPause");
        // state = storyBodyTextView.onSaveInstanceState();
        scrollY = storyBodyScrollView.getScrollY();
        Log.i("onPause scroll", Integer.toString(scrollY));
        // Log.i("insert", Integer.toString(storyID));
        DatabaseHelper db = new DatabaseHelper(this);
        db.setScrollPosition(scrollY, storyID);
        super.onPause();
    }

    @Override
    public void onResume(){
        super.onResume();
        Log.i("onResume scroll", Integer.toString(scrollY));
        storyBodyScrollView.scrollTo(0, scrollY);

    }
}

已解决

使用下面接受的答案的组合,并解决我的 ScrollView 的问题(解决方案 here)。

【问题讨论】:

  • @PragatiSingh 抱歉,我不明白。你能改写一下吗?
  • 你能分享完整的代码(项目),以便我可以运行和测试它,如果它适合你的话。或者您可以创建示例应用程序(项目)来执行此操作并共享该应用程序。
  • 你打开数据库的路径是否正确?
  • 它在 SQLite Asset Helper 指定的 /assets/databases 文件夹中,但我没有在我的代码中指定文件路径。
  • 您正在使用外部应用程序打开什么数据库文件?

标签: android sqlite


【解决方案1】:

资产是只写/受保护的,如果您需要更新数据库,则必须确保将其复制到可以更新的位置。例如默认的 /data/data/your_package/databases/ 文件夹。

SQLiteAssethelper 会简单地做到这一点。

但是当我在外部 DB Browser for SQLite 应用程序中打开我的数据库时, 数据库没有任何变化。

您是否希望setScrollPosition 插入新行或更新现有行?按照编码,它将执行后者。

不推荐使用 execSQL 来执行更新,而 SQLiteDatabase update 方法的优点是它返回执行的更新次数。因此,我建议更改:-

public int setScrollPosition(int scrollY, int storyID) {

    String insertQuery = "UPDATE " + BOOKS + " SET scroll_position = " + scrollY + " WHERE id = " + storyID;
    Log.i("insert", insertQuery);
    SQLiteDatabase db = this.getWritableDatabase();
    db.execSQL(insertQuery);

    return scrollY;

}

到:-

public int setScrollPosition(int scrollY, int storyID) {
    Contentvalues cv = new Contentvalues();
    cv.put("scroll_position", scrolly);
    String whereclasue = "id=?";
    String[] whereargs = new String[]{storyID}; 

    SQLiteDatabase db = this.getWritableDatabase();
    int updates = db.update(BOOKS,cv,whereclause,whereargs);
    if (updates > 0) {
        Log.i("update","Updated " + Integer.toString(updates) + " rows.";
    } else {
        log.i("update","No Updates performed");
    }
    return scrollY;
}

您可能希望更改方法以返回更新的行数。

如果您使用上述方法并且在日志中得到未执行更新,那么这可能会突出显示数据库未更改的原因。

澄清一下,更新的数据库不是资产文件夹中的数据库,而是位于data/data/your_package/databases/database9.db的数据库

您不妨看看this。这包括允许您检查数据库和表的方法。

【讨论】:

  • 我一直在读。 SQLiteAssetHelper 会自动执行此操作还是我需要做些什么?
  • @Sebastian 我已经更新了答案,希望这更有帮助。我从未真正使用过 SQLiteAssetHelper,而是对使用资产数据库进行了一些相当广泛的探索,例如答案here.
  • 感谢您的更新,很抱歉我的回复延迟。我已经实现了您建议的代码,它按预期记录了Updated 1 rows.,但数据库没有更新。如何确保我使用的是正确的数据库?
  • 在答案中使用link(底线)在您的项目中创建一个 CommonSQLiteUtilities 类并复制链接中的代码(注意来自第二篇文章 Addition - logDatabaseInfo)。然后使用实用程序,例如`CommonSQLiteUtilities.logDatabaseInfo(db);`.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-03
  • 1970-01-01
  • 2021-10-06
  • 2014-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多