无法在未使用 AsyncTask 调用 Looper.prepare() 的线程内创建处理程序

发布于 2025-01-06 20:05:18 字数 3222 浏览 1 评论 0原文

我正在尝试在 android 上使用 AsyncTask 类,但遇到问题。

这是我的代码:

 public void CheckIfUserIsLogedIn ()
{
    int userPresence = localDatabase.CheckUserPresence();
    if (userPresence == 0) 
    {
        setContentView(R.layout.main);
        new checkCountryAsync().execute();
    }
    else
    {
        setContentView(R.layout.userlogedon);
    }
}  

class checkCountryAsync extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute(); 
    }
    @Override
    protected String doInBackground(String... aurl) {
        int countryPresence = localDatabase.CheckCountryPresence();
        if (countryPresence == 0) 
        {
            CountryTable country = new CountryTable() ;
            country.EnterCountry();
        }
        return null;
    }
}

我不知道我在哪里做错了。 LocalDatabase 类中的 CheckCountryPresence() 方法仅进行查询并返回结果。

谢谢。

编辑:这是 logCat:

02-20 08:41:25.804: W/dalvikvm(26458): threadid=10: thread exiting with uncaught exception (group=0x4001d5a0)
02-20 08:41:25.834: E/AndroidRuntime(26458): FATAL EXCEPTION: AsyncTask #1
02-20 08:41:25.834: E/AndroidRuntime(26458): java.lang.RuntimeException: An error occured while executing doInBackground()
02-20 08:41:25.834: E/AndroidRuntime(26458):    at android.os.AsyncTask$3.done(AsyncTask.java:200)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.lang.Thread.run(Thread.java:1027)
02-20 08:41:25.834: E/AndroidRuntime(26458): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
02-20 08:41:25.834: E/AndroidRuntime(26458):    at android.os.Handler.<init>(Handler.java:121)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at android.app.Activity.<init>(Activity.java:717)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at milos.mdpi.CountryTable.<init>(CountryTable.java:5)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at milos.mdpi.MDPIActivity$checkCountryAsync.doInBackground(MDPIActivity.java:367)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at milos.mdpi.MDPIActivity$checkCountryAsync.doInBackground(MDPIActivity.java:1)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at android.os.AsyncTask$2.call(AsyncTask.java:185)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
02-20 08:41:25.834: E/AndroidRuntime(26458):    ... 4 more

I am trying to use the AsyncTask class on android but I have a problem.

Here is my code:

 public void CheckIfUserIsLogedIn ()
{
    int userPresence = localDatabase.CheckUserPresence();
    if (userPresence == 0) 
    {
        setContentView(R.layout.main);
        new checkCountryAsync().execute();
    }
    else
    {
        setContentView(R.layout.userlogedon);
    }
}  

class checkCountryAsync extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute(); 
    }
    @Override
    protected String doInBackground(String... aurl) {
        int countryPresence = localDatabase.CheckCountryPresence();
        if (countryPresence == 0) 
        {
            CountryTable country = new CountryTable() ;
            country.EnterCountry();
        }
        return null;
    }
}

I don't know where I am doing something wrong. The method CheckCountryPresence() from the LocalDatabase class is only making a query and returns a result.

Thank you.

Edit: Here is the logCat:

02-20 08:41:25.804: W/dalvikvm(26458): threadid=10: thread exiting with uncaught exception (group=0x4001d5a0)
02-20 08:41:25.834: E/AndroidRuntime(26458): FATAL EXCEPTION: AsyncTask #1
02-20 08:41:25.834: E/AndroidRuntime(26458): java.lang.RuntimeException: An error occured while executing doInBackground()
02-20 08:41:25.834: E/AndroidRuntime(26458):    at android.os.AsyncTask$3.done(AsyncTask.java:200)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.lang.Thread.run(Thread.java:1027)
02-20 08:41:25.834: E/AndroidRuntime(26458): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
02-20 08:41:25.834: E/AndroidRuntime(26458):    at android.os.Handler.<init>(Handler.java:121)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at android.app.Activity.<init>(Activity.java:717)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at milos.mdpi.CountryTable.<init>(CountryTable.java:5)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at milos.mdpi.MDPIActivity$checkCountryAsync.doInBackground(MDPIActivity.java:367)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at milos.mdpi.MDPIActivity$checkCountryAsync.doInBackground(MDPIActivity.java:1)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at android.os.AsyncTask$2.call(AsyncTask.java:185)
02-20 08:41:25.834: E/AndroidRuntime(26458):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
02-20 08:41:25.834: E/AndroidRuntime(26458):    ... 4 more

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眉黛浅 2025-01-13 20:05:18

似乎您正在做一些事情来从非 UI 线程更新您的 UI。因此,您应该将要更新 UI 的内容放入 runOnUiThread() 中,以便它在您的 UI 线程本身上执行这些内容。

更新:

只需尝试将获取 CheckCountryPresence(); 的内容放入 onPreExecute() 中即可。所以你编辑的课程应该是这样的,

class checkCountryAsync extends AsyncTask<String, String, String> {

    int countryPresence = 0;
    @Override
    protected void onPreExecute() {
       countryPresence = localDatabase.CheckCountryPresence();
    }
    @Override
    protected String doInBackground(String... aurl) {

        Activity_name.this.runOnUiThread(new Runnable() {

        @Override
        public void run() {
            if (countryPresence == 0) 
            {
              CountryTable country = new CountryTable() ;
              country.EnterCountry();
            }
        }
    });
        return null;
    }
}

Seems you are doing some stuff to Update your UI from a Non-UI thread. So, you should put your stuff to update the UI inside runOnUiThread() so that it executes the stuff on your UI hread itself.

UPDATE:

Just try to put your stuff for getting CheckCountryPresence(); inside onPreExecute(). So your edited class should be like,

class checkCountryAsync extends AsyncTask<String, String, String> {

    int countryPresence = 0;
    @Override
    protected void onPreExecute() {
       countryPresence = localDatabase.CheckCountryPresence();
    }
    @Override
    protected String doInBackground(String... aurl) {

        Activity_name.this.runOnUiThread(new Runnable() {

        @Override
        public void run() {
            if (countryPresence == 0) 
            {
              CountryTable country = new CountryTable() ;
              country.EnterCountry();
            }
        }
    });
        return null;
    }
}
何处潇湘 2025-01-13 20:05:18

您的 CountryTable 类与 UI 活动/类有任何交互吗?甚至为您的适配器对象获取新行?
如果是,您无法从活动本身外部更新您的活动。

幸运的是,一旦找到解决方案,您就可以轻松克服这个问题;)

第 1 步:

定义一个接口,例如使用名为 onCheckCountryFinished(String taskResult) 的单个方法定义一个接口,例如 CheckCountryCallback

步骤2:让调用你的asynctask的活动实现这个接口及其方法。

步骤 3:使用 CheckCountryCallback 类型的单个参数为 asyncTask 定义一个构造函数

步骤 4:重写 AT 的 onPostExecute,并简单地编写 mCaller.onCheckCountryFinished(result)。

遗憾的是,这还不够,因为您仍然需要从另一个线程更新 ui,但我们已经很接近了!

在实现的 onCheckCountryFinished 中,您应该将调用重定向到您在活动中定义的处理程序。向该处理程序发送消息,您可以通过处理程序的处理消息方法更新 UI(或适配器或其他内容)。

处理程序示例:

private static final int UPDATE = 2;
private Handler handler = new Handler() {

    public void handleMessage(Message msg) {
        if (msg.what == UPDATE) {
               //do something with m.obj
               myAdapter.notifyDataSetChanged();
        }
    }
};

回调示例

public void onCheckCountryFinished(String result){
    Message m = Message.obtain();
    m.what = UPDATE;
    m.obj = result;
    handler.sendMessage(m);
}

Has your CountryTable class any interaction with the UI activity/class? Even fetching new rows for your adapter object?
If yes, you cannot update your activity from outside the activity itself.

Fortunately you can overcome this pretty easily once you figure out the solution ;)

step 1:

Define an interface, like CheckCountryCallback with a single method called onCheckCountryFinished(String taskResult);

Step 2: let the activity which call your asynctask implement this interface and its method.

Step 3: define a constructor for your asyncTask with a single parameter of type CheckCountryCallback

Step 4: override onPostExecute of your AT, and simply write mCaller.onCheckCountryFinished(result).

This is not enough sadly because you'd still be updating the ui from another thread but we're getting close!

In your implemented onCheckCountryFinished you should redirect the call to a handler you've to define in your activity. Send a message to that handler and you can update the UI (or the adapter or whatnot) from the handle message method of the handler.

Handler example:

private static final int UPDATE = 2;
private Handler handler = new Handler() {

    public void handleMessage(Message msg) {
        if (msg.what == UPDATE) {
               //do something with m.obj
               myAdapter.notifyDataSetChanged();
        }
    }
};

callback example

public void onCheckCountryFinished(String result){
    Message m = Message.obtain();
    m.what = UPDATE;
    m.obj = result;
    handler.sendMessage(m);
}
烧了回忆取暖 2025-01-13 20:05:18

您没有向 AsyncTask 传递任何内容,因此请将 AsyncTask 的参数设置为 Void,如下所示 AsyncTask 然后将 doInBackground 更改为此 protected Void doInBackground (无效...无效)。另外,摆脱 onPreExecute 方法,因为您甚至没有使用它。

另外,您提供的代码还不清楚,但需要从 UI 线程调用 CheckIfUserIsLogedIn 。 AsyncTask 实际上只是在 UI 线程上运行。

You are not passing your AsyncTask anything so make the parameters of AsyncTask all Void like this AsyncTask<Void, Void, Void> then change doInBackground to this protected Void doInBackground(Void... voids). Also, get rid of the onPreExecute method since you are not even using it.

Also, it is unclear with you code provided, but CheckIfUserIsLogedIn needs to be called from the UI thread. AsyncTask is really only meant to be run off of the UI thread.

沧笙踏歌 2025-01-13 20:05:18

我遇到的问题之一是,当从thread调用时,simpleCursorAdapter也会返回相同的looper错误。因此,要消除该错误,请使用内部线程

ActivityName.this.runOnUiThread(new Runnable() {
 public void run() {
   String[] FROM = {/*your data here*/};
int[] TO = { /*your data here*/ };
adapter = new SimpleCursorAdapter(ActivityName.this, R.layout.row, cursor, FROM, TO);   
listTimeline.setAdapter(adapter); //your own code here.
}
});

one of the problem that i faced, simpleCursorAdapter also returns same error of looper when called from thread. So to remove that error, inside thread

ActivityName.this.runOnUiThread(new Runnable() {
 public void run() {
   String[] FROM = {/*your data here*/};
int[] TO = { /*your data here*/ };
adapter = new SimpleCursorAdapter(ActivityName.this, R.layout.row, cursor, FROM, TO);   
listTimeline.setAdapter(adapter); //your own code here.
}
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文