如果我在 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 数据库?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 AsyncTask 会冻结我的 UI 线程?

为啥我的 AsyncTask 在主线程上运行?

如何在AsyncTask doInBackground()中使用同步对象?

用于存储到数据库中的 AsyncTask 或服务或线程

Asynctask vs 线程 vs 服务 vs 加载器

如何在 Java 线程中将记录插入数据库?