如果我在 AsyncTask 线程中插入数据,如何从 UI 线程访问 SQLite 数据库?
Posted
技术标签:
【中文标题】如果我在 AsyncTask 线程中插入数据,如何从 UI 线程访问 SQLite 数据库?【英文标题】:How to access SQLite database from UI thread if I'm inserting data in AsyncTask thread? 【发布时间】:2012-09-24 12:01:56 【问题描述】:我的 android 应用程序中有一个名为 Main.java 的类,用于根据服务器中的数据验证用户登录名(用户名 + 密码)。起初,我成功了;我使用了一个 AsyncTask 线程加上一个处理 Http 连接的库,调用 HttpPostAux.java(事实上,我在这个论坛上找到了库的代码)。在 AsyncTask 的 onPostExecute 方法中,我创建并启动了一个新活动,而不是修改当前活动,并且它起作用了。
但现在我想做一些不同的事情。我想将经过验证的数据(用户名 + 密码)保存到 AsyncTask 线程中的 SQLite 表中,然后在 UI 线程中,恢复该数据并使用它来打开提到的活动。插入发生但是当我试图从 UI 线程访问数据库时:它说表是空的。所以我查看了logcat,发现UI线程在AsyncTask线程之前执行。
所以我的问题是如何在 AsyncTask 线程中插入数据,然后在 UI 线程中恢复它?有人可以帮忙吗?我有点迷路了!
我会欣赏一个代码示例!提前致谢! 来自委内瑞拉的问候!
【问题讨论】:
你能用代码显示你在做什么吗? 当然可以。这就是 onPostExecute 的用途。在你的 asynctask 完成它必须做的事情之后在 ui 线程上执行东西 【参考方案1】:UI 线程是您的应用程序主线程。当您创建AsyncTask
时,您的耗时任务将在单独的线程上执行(在doInBackground
函数内)。当doInBackground
完成时,将从UI 线程调用onPostExecute()
。因此,您只需从onPostExecute()
内部执行您的 UI 线程任务(=“恢复该数据并使用它来打开提到的活动”)。
【讨论】:
【参考方案2】:我认为你之前的做法是正确的。我建议进行一种 SplashScreen 活动,检查用户之前是否登录过,即数据库中是否有用户名/密码。如果是这种情况,请使用此数据登录用户,然后继续您的主要活动。如果用户之前没有登录过,请使用登录屏幕提示他们,存储此数据以供将来使用并继续您的主要活动。
【讨论】:
【参考方案3】:你可以在你的 UIThread 中实现一个 BroadcastReciever,当插入数据库完成时,它会监听从你的 AsyncTask 发送的 Intent。
从 AsyncTask 触发:
Intent intent = new Intent("DATABASE_INSERTION_DONE");
context.sendBroadcast(intent );
在 UiThread 中注册:
IntentFilter intentFilter = new IntentFilter("DATABASE_INSERTION_DONE");
registerReceiver(myIntentsReceiver, intentFilter);
类:
class MyIntentReceiver extends BroadcastReceiver
@Override
public void onReceive(Context context, Intent intent)
if ("DATABASE_INSERTION_DONE".equals(intent.getAction()))
//do something
【讨论】:
【参考方案4】:您必须记住,一旦您启动 AsyncTask,它将在另一个线程上运行,并且您的 UI 线程将继续前进。例如:
x="foo";
new SampleAsyncTask().execute();
txtView.setText(x);
Class SampleAsyncTask extends AsyncTask<...>
.....
public Void doInBackground(...)
//LOTS OF CALCULATIONS
x="bar";
您的 txtView 肯定会显示“foo”而不是“bar”。为了确保您的 AsyncTask 完成,有很多选项。您可以在 AsyncTask 的 PostExecute 中调用方法来启动其余操作。你也可以像 Jelgh 所说的那样使用意图和广播接收器。但我最喜欢的是使用简单的回调:
public class LoginActivity extends Activity implement SampleAsyncTask.asyncCallback
@Override
protected void onCreate(Bundle savedInstanceState)
x="foo";
new SampleAsyncTask().execute();
Class SampleAsyncTask extends AsyncTask<...>
asyncCallback mCallback;
public SampleAsyncTask(Context c)
mCallback; = (asyncCallback) c
public interface asyncCallback
void servedMyPurposeYouCanGoOn();
public Void doInBackground(...)
//LOTS OF CALCULATIONS
x="bar";
mCallback.servedMyPurposeYouCanGoOn;
//REST OF THE WORK
@Override
public void servedMyPurposeYouCanGoOn()
runOnUIThread(
//rest of the work
)
【讨论】:
以上是关于如果我在 AsyncTask 线程中插入数据,如何从 UI 线程访问 SQLite 数据库?的主要内容,如果未能解决你的问题,请参考以下文章