IT

Android SDK AsyncTask doInBackground가 실행되지 않음 (하위 클래스)

lottoking 2020. 9. 4. 07:41
반응형

Android SDK AsyncTask doInBackground가 실행되지 않음 (하위 클래스)


2012 년 2 월 15 일 현재 나는 작동하지 않는 이유에 좋은 설명이나 이유를 아직 찾지 못합니다. 솔루션에 가장 가까운 방법은 기존의 접근 방식 방식 을 사용하는 것이지만 Android SDK에서 작동하지 않는 클래스를 포함하는 이유는 무엇입니까?

Evenin 'SO!

AsyncTask 하위 클래스가 있습니다.

// ParseListener had a callback which was called when an item was parsed in a
// RSS-xml, but as stated further down it is not used at all right now.
private class xmlAsync extends AsyncTask<String, RSSItem, Void> implements ParseListener

다음과 같이 실행됩니다.

xmlAsync xmlThread = new xmlAsync();

xmlThread.execute("http://www.nothing.com");

이제이 하위 클래스에 약간의 오류가 발생했습니다. 이전에는 xml 구문 분석을 수행했지만 doInBackground () 가 호출되지 않은 것을 알았을 때 한 줄씩 제거하고 마침내 다음과 같이 끝납니다.

@Override
protected Void doInBackground(String... params) 
{
    Log.v(TAG, "doInBackground");
        return null;
}

어떤 아무 것도 아무것도 기록하지 않습니다. 그러나 나는 추가했다.

@Override
protected void onPreExecute() 
{
        Log.v(TAG, "onPreExecute");
        super.onPreExecute();
}

그리고 그 줄은 언어를 사용할 때 기록합니다. 그래서 어떻게 든 onPreExecute ()가 호출하는 언어는 아닙니다 . 나는 다른 AsyncTask가 백그라운드에서 동시에 실행되어 작동합니다.

현재 북극에 가까운 에뮬레이터 SDK 버전 15, Eclipse, Mac OS X 10.7.2에서 앱을 실행하고 있습니다.

편집하다 :

@Override
    protected void onProgressUpdate(RSSItem... values) {

        if(values[0] == null)
        {
                            // activity function which merely creates a dialog
            showInputError();
        }
        else
        {

            Log.v(TAG, "adding "+values[0].toString());
            _tableManager.addRSSItem(values[0]);
        }


        super.onProgressUpdate(values);
    }

_tableManager.addRSSItem () 다소간은 활동의 초기화로 초기화 된 SQLiteDatabase에 행을 추가합니다. publishProgress (는 Interface ParseListener의)에 의해 호출됩니다. 그러나 doInBackground ()에서 log.v 외에는 아무것도하지 않아 갑자기 발생하는 것이 발견되었습니다.

편집 2 :

좋아, 분명히 말하면, 동일 활동에서 실행되고 완벽하게 작동하는 다른 AsyncTask입니다.

private class dbAsync extends AsyncTask<Void, RSSItem, Void>
{
    Integer prevCount;
    boolean run;

    @Override
    protected void onPreExecute() {
        run = true;
        super.onPreExecute();
    }

    @Override
    protected Void doInBackground(Void... params) {
        // TODO Auto-generated method stub
        run = true;
        prevCount = 0;

        while(run)
        {
            ArrayList<RSSItem> items = _tableManager.getAllItems();

            if(items != null)
            {
                if(items.size() > prevCount)
                {
                    Log.v("db Thread", "Found new item(s)!");
                    prevCount = items.size();

                    RSSItem[] itemsArray = new RSSItem[items.size()];

                    publishProgress(items.toArray(itemsArray));
                }
            }               

            SystemClock.sleep(5000);
        }

        return null;
    }

    @Override
    protected void onProgressUpdate(RSSItem... values) {

        ArrayList<RSSItem> list = new ArrayList<RSSItem>();

        for(int i = 0; i < values.length; i++)
        {
            list.add(i, values[i]);
        }

        setItemsAndUpdateList(list);

        super.onProgressUpdate(values);
    }

    @Override
    protected void onCancelled() {
        run = false;

        super.onCancelled();
    }
}

편집 3 :

한숨, 미안 해요 질문을 못해요. 그러나 여기에 태스크의 초기화가 있습니다.

xmlAsync _xmlParseThread;
dbAsync _dbLookup;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

_dbLookup = new dbAsync();
_dbLookup.execute();

_xmlParseThread = new xmlAsync();       
_xmlParseThread.execute("http://www.nothing.com", null);
}

Matthieu의 솔루션은 대부분 잘 작동하지만 일부는 문제에 직면 할 수 있습니다. 여기에 제공된 많은 링크 또는 Anders Göransson 의 설명 과 같이 웹에서 파헤쳐지지 않는 한 . 여기에 다른 읽기를 요약하고 executeOnExecutor가 여전히 단일 스레드에서 작동하는 경우 솔루션을 빠르게 설명하려고합니다.

의 동작이 AsyncTask().execute();Android 버전을 통해 변경되었습니다. 전에 도넛 (안드로이드 1.6 API : 4) 작업에서 연속적으로 실행 된 도넛진저 브레드 (안드로이드 2.3 API : 9) 작업을 병렬로 실행; Honeycomb (Android : 3.0 API : 11) 실행이 다시 순차적으로 전환 되었기 때문에 ; AsyncTask().executeOnExecutor(Executor)그러나 병렬 실행을 위해 새로운 방법 이 추가되었습니다.

순차 처리에서 모든 비동기 작업은 단일 스레드에서 실행되므로 이전 작업이 종료되기 전에 기다려야합니다. 코드를 즉시 실행해야하는 경우 별도의 스레드에서 병렬로 처리 할 작업이 필요합니다.

AsyncTask를 사용하면 Donut과 Honeycomb 버전간에 직렬 실행을 사용할 수 없지만 Donut 이전에는 병렬 실행을 사용할 수 없습니다.

Donut 이후 병렬 처리 : 빌드 버전을 확인하고이를 기반으로 .execute () 또는 .executeOnExecutor () 메서드를 사용합니다. 다음 코드가 도움이 될 수 있습니다 ...

AsyncTask<Void,Void,Void> myTask = new AsyncTask<Void,Void,Void>() { ... }; // ... your AsyncTask code goes here
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB)
    myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
else
    myTask.execute();

NOTE:함수 .executeOnExecutor()targetSdkVersion프로젝트가 HONEYCOMB_MR1(Android : 2.1 API : 7) 보다 작거나 같은지 확인한 다음 실행기를 강제 실행합니다 THREAD_POOL_EXECUTOR(Honeycomb 이후 작업을 순차적으로 실행).
당신이 정의하지 않은 경우 targetSdkVersion다음 minSdkVersion자동으로 간주됩니다 targetSdkVersion.
따라서 Honeycomb 이후에 AsyncTask를 병렬로 실행하려면 targetSdkVersion비워 둘 수 없습니다 .


이 답변을 확인해야합니다 : https://stackoverflow.com/a/10406894/347565 및 포함 된 Google 그룹에 대한 링크.

나는 당신과 비슷한 문제가 있었지만 왜 작동하지 않는지 명확하지 않지만 다음과 같이 코드를 변경하고 문제가 사라졌습니다.

ASyncTask<Void,Void,Void> my_task = new ASyncTask<Void,Void,Void>() { ... };
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
    my_task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[])null);
else
    my_task.execute((Void[])null);

다음 두 가지 방법으로이 작업을 수행 할 수 있습니다.

방법 1 :

if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) // Above Api Level 13
  {
      asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
  }
else // Below Api Level 13
  {
      asyncTask.execute();
  }

방법 1 이 작동하지 않는 경우 방법 2 를 시도하십시오 .

방법 2 :

int mCorePoolSize = 60;
int mMaximumPoolSize = 80;
int mKeepAliveTime = 10;
BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>(mMaximumPoolSize);
Executor mCustomThreadPoolExecutor = new ThreadPoolExecutor(mCorePoolSize, mMaximumPoolSize, mKeepAliveTime, TimeUnit.SECONDS, workQueue);
asyncTask.executeOnExecutor(mCustomThreadPoolExecutor);

이것이 당신을 도울 것입니다.


나는 똑같은 문제가 있었다 : 내가 첫번째 것에 "execute"를 호출 한 후에 두번째 AsyncTask를 실행할 수 없다 : doInBackground는 첫번째 것에 대해서만 호출된다.

왜 이런 일이 발생하는지 대답 하려면이 대답을 확인하십시오 (SDK에 따라 다른 동작).

그러나 귀하의 경우이 장애물은 executeOnExecutor를 사용하여 피할 수 있지만 (4.0.3을 사용하여 3.0부터 사용 가능) 스레드 풀 크기 및 대기열 제한에 유의하십시오.

다음과 같이 시도해 볼 수 있습니까?

xmlAsync _xmlParseThread;
dbAsync _dbLookup;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

_dbLookup = new dbAsync();
_dbLookup.execute();

_xmlParseThread = new xmlAsync();       
_xmlParseThread.executeOnExecutor(_dbLookup.THREAD_POOL_EXECUTOR
 ,"http://www.nothing.com", null);
}

업데이트 질문의 경우 : 기본적으로 intereference와 같은 다중 스레딩에서 올 수있는 모든 문제를 피하기 위해 문서에 설명되어 있습니다.


내가 알고 싶은 한 가지는 실제로 문제를 해결할 수 있습니다. 클래스의 인스턴스를 인스턴스화하고 execute () 메서드를 호출하는 것입니다. AsyncTask에 대한 문서를 읽으면 두 작업 모두 기본 UI 스레드에서 수행되어야합니다. 개체를 만들고 다른 스레드에서 execute를 호출하는 경우 onPreExecute가 실행될 수 있습니다. 여기서 100 % 확실하지는 않지만 백그라운드 스레드가 생성 및 실행되지 않습니다.

백그라운드 스레드에서 AsyncTask의 인스턴스를 만들거나 기본 UI 스레드에서 발생하지 않는 다른 작업을 만드는 경우 다음 메서드를 사용할 수 있습니다. Activity.runOnUiThread (Runnable)

해당 메서드를 호출하려면 실행중인 Activity의 인스턴스에 액세스해야하지만 UI 스레드에서 실행되지 않는 다른 코드에서 UI 스레드에서 코드를 실행할 수 있습니다.

이해가 되길 바랍니다. 도움이 더 필요하면 알려주세요.

데이비드


Android는 잔인합니다! 나는 이것을 믿을 수 없다. 날마다 변화하는 잘못된 구현이다. 하루는 단일 스레드이고 다음은 5이고 다른 스레드는 128입니다.

어쨌든 여기에 주식 AsyncTask를 대체하는 거의 하락이 있습니다. 원하는 경우 AsyncTask라고 부를 수도 있지만 혼동을 피하기 위해 ThreadedAsyncTask라고합니다. execute ()가 최종이므로 execute 대신 executeStart ()를 호출해야합니다.

/**
 * @author Kevin Kowalewski
 *
 */
public abstract class ThreadedAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> { 
    public AsyncTask<Params, Progress, Result> executeStart(Params... params){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
            return executePostHoneycomb(params);
        }else{
            return super.execute(params);
        }
    }


    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    private AsyncTask<Params, Progress, Result> executePostHoneycomb(Params... params){
        return super.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); 
    }
}

나는 이것이 스레드에 대해 정말 늦을 수 있다는 것을 알고 있지만 나중에 안드로이드 에뮬레이터에서 작동하지 않는 이유가 있습니다. asynctask가 소개되었을 때 android는 한 번에 하나씩 만 실행할 수있게했고, 나중에 어떤 버전인지 잘 모르겠습니다. 한 번에 여러 비동기 작업을 실행할 수 있었으며 이로 인해 많은 앱에서 문제가 발생했으며 Honeycomb +에서는 다음으로 만 되돌아갔습니다. 한 번에 하나의 비동기 작업을 실행할 수 있습니다. 스레드 풀을 수동으로 변경하지 않는 한. 사람들을 위해 한두 가지를 정리하기를 바랍니다.


나는 그 sdk라고 생각한다. 나는 같은 문제가 있었고 대상 SDK를 15에서 11로 변경 한 후 모든 것이 완벽하게 작동합니다.

sdk15를 사용하면 AsyncTask.Status가 RUNNING이지만 doInBackground가 호출되지 않습니다. 나는 그것이 ui 스레드와 관련이 있다고 생각합니다.


Matthieu의 답변에 따라 애플리케이션에서 코드가 중복되는 것을 방지하기 위해 SDK 버전에 따라 올바르게 실행 하는 도우미 클래스 아래 AsyncTask:

import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.os.Build;

public class AsyncTaskExecutor<Params, Progress, Result> {

  @SuppressLint("NewApi")
  public AsyncTask<Params, Progress, Result> execute(final AsyncTask<Params, Progress, Result> asyncTask, final Params... params){
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
      return asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
    }  else{
      return asyncTask.execute(params);
    }
  }

}

사용 예 :

public class MyTask extends AsyncTask<Void, Void, List<String>> {

...

final MyTask myTask = new MyTask();
new AsyncTaskExecutor<Void, Void, List<String>>().execute(myTask);

참고 URL : https://stackoverflow.com/questions/9119627/android-sdk-asynctask-doinbackground-not-running-subclass

반응형