Android中如何在数据库中获取上下文信息

3
我有一个数据库,创建了一个名为Database的类,其中包含一个private static class DbHelper extends SQLiteOpenHelper,以帮助我管理数据库。
这个数据库从四个不同的活动中访问。
我有一个public void onCreate(SQLiteDatabase db)方法,用于创建我的数据库表并向这些表添加值。由于程序只在用户首次运行应用程序时进入此处,因此我想创建一个ProgressDialog
这是我目前拥有的内容:
Override
public void onCreate(SQLiteDatabase db) {

    ProgressDialog progresso = ProgressDialog.show(context, "Info", "Loading DB" );
    // Code to create the tables and add the values
    progress.dismiss();
}

我有两个问题。

第一个问题:

由于这可以从4个不同的活动访问,那么我该如何获取上下文?

制作中:

Context context = getAplicationContext();

第二点:

为什么我不能使用来自strings.xml的字符串? 我无法完成这个操作:

ProgressDialog progresso = ProgressDialog.show(context, getString(R.string.driProgressTitle), getString(R.string.driProgressMessage) );

更新

public class Database {
    ProgressDialog progresso;
    private DbHelper DBHelper;
    private final Context Context;
    private SQLiteDatabase BaseDados;

    private static class DbHelper extends SQLiteOpenHelper {

        public DbHelper(Context context) {
            super(context, BD_NAME, null, BD_VERSION);
            // TODO Auto-generated method stub
        }

        @Override
        public void onCreate(SQLiteDatabase db) {

        // Whanted to show here the progress dialog
        new loadDB().execute();

        // Creates the table and adds the values

        }

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

    }

    public Database(Context c) {
        Context = c;
    }

    public Database open() throws SQLException {
        DBHelper = new DbHelper(Context);
        BaseDados = DBHelper.getWritableDatabase();
        return this;
    }

    public void close() {
        DBHelper.close();
    }

    public Cursor getData(int tipo, long groupId, String query[]) {
        // Performs the querys to my database
    }
    return null;
}

    public class loadDB extends AsyncTask<Void, Void, Integer> {

        @Override
        protected Integer doInBackground(Void... params) {
            progresso = ProgressDialog.show(Context, Context.getString(R.string.ProgressTitle), Context.getString(R.string.ProgressMessage) );
            return 1;
        }

        @Override
        protected void onPostExecute(Integer result) {
            progresso.dismiss();
            super.onPostExecute(result);
        }
    }
}

使用上面的代码时,我得到了这个错误No enclosing instance of type Database is accessible. Must qualify the allocation with an enclosing instance of type Database (e.g. x.new A() where x is an instance of Database).new loadDB().execute();中。


1
不,你不能在doInBackground()方法中触及任何与GUI相关的内容。重写onPreExecute()并在其中调用ProgressDialog.show() - S.D.
@wingman 好的。已经完成了。但是我在哪里调用 new loadDB().execute(); - Favolas
在您的活动的“onStart()”方法内部,任何地方都可以,除了“loadDB”之外。 - S.D.
@wingman 在我的 Database 类的 onCreate(SQLiteDatabase db) 中执行 new loadDB().execute(); 时出现了错误:No enclosing instance of type Database is accessible. Must qualify the allocation with an enclosing instance of type Database (e.g. x.new A() where x is an instance of Database). 在我的主类/活动的 onCreate(Bundle savedInstanceState) 中执行 new loadDB().execute(); 时出现了错误:loadDB cannot be resolved to a type。感谢您的帮助。 - Favolas
5个回答

8

您的构造函数中没有访问上下文的权限吗?

SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)

SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) 

编辑:

你的代码:

public DbHelper(Context context) {
        super(context, BD_NAME, null, BD_VERSION);
        // TODO Auto-generated method stub
    }

在这一点上,您可以访问上下文。您可以添加一个名为"context"的字段,然后执行以下操作:

Context context;
public DbHelper(Context context) {
        super(context, BD_NAME, null, BD_VERSION);
        // TODO Auto-generated method stub
        this.context = context;
    }

现在,您可以在类中的任何位置访问上下文吗? 假设构造函数在onCreate之前被调用。


我的构造函数不是那样的。请查看我的更新问题。 - Favolas
谢谢。现在问题出在new loadDB().execute();上。在我的Database类的onCreate(SQLiteDatabase db)中执行new loadDB().execute();会出现以下错误:No enclosing instance of type Database is accessible. Must qualify the allocation with an enclosing instance of type Database (e.g. x.new A() where x is an instance of Database). 在我的主类/活动的onCreate(Bundle savedInstanceState)中执行new loadDB().execute();会出现错误:loadDB cannot be resolved to a type. - Favolas
1
你的内部类需要引用外部类。在这里阅读:https://dev59.com/3XRB5IYBdhLWcg3wZmhz - corgichu
@cskoalo 谢谢。它可以正常运行,但现在它不显示 ProgressDialog。如果您有时间,这是代码:http://pastebin.com/M5pJc6fy - Favolas

1

onCreate(SQLiteDatabase)方法只在第一次调用getReadableDatabase()getWritableDatabase时被调用(即第一次打开它),而不是在应用程序第一次运行时调用(当然,您可以通过简单地打开数据库并关闭它来实现这一点)。

我不确定将其提供给应用程序上下文是否有效,因为进度对话框需要显示在当前正在运行的Activity中。

与其尝试精确地在首次访问数据库时显示进度条,不如让当前Activity在访问数据库本身时显示一个进度条。这样,对数据库的第一次访问就被常规访问所掩盖。

如果您不想为所有DB访问显示进度条,那么您可以只打开和关闭数据库,并在打开它之前让您的Activity显示一个进度条,在关闭它时删除进度条(除了让onCreate()运行之外,不对数据库进行任何操作)。

除非您的数据库结构真的很大,否则您可能甚至看不到进度条。创建表格不需要太长时间。


1
使用Loader从数据库中读取数据。不要在后台类中混杂UI相关的内容。
onCreateLoader(.. 
   //you can start progress

onLoadFinished(..
   // you can stop it

同时建议您从后台线程读取数据。


0

你无法访问应用程序的上下文,因为SQLiteOpenHelper没有包含这些方法(不像Activity)

我给你的建议是使用DbHelper类来设置数据库并管理任何SQL事务。让它的构造函数接受一个上下文对象,然后在扩展Activity的类中创建它的实例,通过构造函数将上下文传递进去。

还有一个好的做法是在活动和SQLiteOpenHelper之间放置一个数据访问对象类,以管理打开、关闭和发出事务到你的数据库对象。


你可能已经猜到了,应用程序期望有一个数据库实例来执行操作,你在调用的活动中声明了一个数据库实例吗?然后对该实例调用loaddb()方法? - Dnlhoust
抱歉,我不太理解。我应该在调用数据库的活动中执行类似于“Database db = new Database(this); new loadDB()。execute(); db.open();”这样的操作吗? - Favolas
在执行之前尝试打开数据库。 - Dnlhoust

0
为了显示用户进度,您需要在单独的线程中运行工作,否则GUI将会冻结,直到数据库工作完成,用户可能会收到“Activity not responding, force close”消息。
使用Application类来存储关于数据库是否已创建的全局标志。
任何启动活动都会检查此标志,如果尚未初始化数据库,则会创建一个AsyncTask,并在构造函数中传递db和自己的上下文。 AsyncTask将有三个方法:
  1. onPreExecute:在此处显示对话框。使对话框不可取消,以便用户无法跳过它。
  2. doInBackground:在此处编写数据库构建代码。(调用Database helper类方法)
  3. onPostExecute:关闭对话框。现在用户可以与Activity交互。

我按照您的建议进行了操作,但是出现了错误。请查看我的更新问题。 - Favolas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接