Не удается создать обработчик внутри потока, который не вызвал Looper.prepare () с AsyncTask - PullRequest
1 голос
/ 20 февраля 2012

Я пытаюсь использовать класс AsyncTask на Android, но у меня проблема.

Вот мой код:

 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;
    }
}

Я не знаю, где я делаю что-то не так,Метод CheckCountryPresence () из класса LocalDatabase только делает запрос и возвращает результат.

Спасибо.

Редактировать: Вот 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

Ответы [ 4 ]

6 голосов
/ 20 февраля 2012

Кажется, вы делаете что-то для Update вашего интерфейса из потока Non-UI.Таким образом, вы должны поместить свой материал для обновления пользовательского интерфейса внутри runOnUiThread(), чтобы он выполнял материал самого хеда вашего пользовательского интерфейса.положите свои вещи для получения 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;
    }
}
3 голосов
/ 20 февраля 2012

Имеет ли ваш класс CountryTable какое-либо взаимодействие с деятельностью / классом пользовательского интерфейса?Даже выбирая новые строки для вашего объекта адаптера?Если да, вы не можете обновить свою деятельность за пределами самой деятельности.

К счастью, вы можете преодолеть это довольно легко, когда вы найдете решение;)

шаг 1:

Определите интерфейс, например CheckCountryCallback, с помощью одного метода с именем onCheckCountryFinished(String taskResult);

Шаг 2: пусть действие, вызывающее вашу асинхронную задачу, реализует этот интерфейс и его метод.

Шаг 3: определитеконструктор для вашей asyncTask с одним параметром типа CheckCountryCallback

Шаг 4: переопределите onPostExecute вашего AT и просто напишите mCaller.onCheckCountryFinished (result).

К сожалению, этого недостаточноМы все еще будем обновлять пользовательский интерфейс из другого потока, но мы приближаемся!

В вашем реализованном onCheckCountryFinished вы должны перенаправить вызов на обработчик, который вы определили в своей деятельности.Отправьте сообщение этому обработчику, и вы можете обновить пользовательский интерфейс (или адаптер или еще что-то) из метода обработчика сообщений обработчика.

Пример обработчика:

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);
}
2 голосов
/ 20 февраля 2012

Вы ничего не передаете своей AsyncTask, поэтому задайте для параметров AsyncTask значение Void, как это AsyncTask<Void, Void, Void>, затем измените doInBackground на это protected Void doInBackground(Void... voids).Кроме того, избавьтесь от метода onPreExecute, поскольку вы даже не используете его.

Кроме того, неясно, какой у вас код, но CheckIfUserIsLogedIn необходимо вызывать из потока пользовательского интерфейса.AsyncTask действительно предназначен для запуска только из потока пользовательского интерфейса.

1 голос
/ 15 марта 2013

одна из проблем, с которыми я столкнулся, simpleCursorAdapter также возвращает ту же ошибку looper при вызове из 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.
}
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...