8

Folks,wzorzec projektowy do połowu nieobsłużonych wyjątków w AsyncTask

złapię nieobsłużonych wyjątków systemu Android za pomocą fragmentu kodu jak ten, na szczycie onCreate:

try { 
     File crashLogDirectory = new File(Environment.getExternalStorageDirectory().getCanonicalPath() + Constants.CrashLogDirectory); 
     crashLogDirectory.mkdirs(); 

     Thread.setDefaultUncaughtExceptionHandler(new RemoteUploadExceptionHandler(
       this, crashLogDirectory.getCanonicalPath())); 
    } catch (Exception e) { 
     if (MyActivity.WARN) Log.e(ScruffActivity.TAG, "Exception setting up exception handler! " + e.toString()); 
    } 

Chciałbym wymyślić coś podobnego do około dwóch tuzinów AsyncTasks, których używam w mojej aplikacji na Androida, więc nieobsługiwane wyjątki, które występują w doInBackground, zostają przechwycone & zarejestrowane.

Problem polega na tym, że AsyncTask przyjmuje inicjatory dowolnego typu, nie jestem pewien, jak zadeklarować nadklasę, z której dziedziczą wszystkie moje funkcje AsyncTasks, która konfiguruje ten nieobsługiwany moduł obsługi wyjątku.

Czy ktoś może polecić dobry wzorzec projektowania do obsługi nieobsługiwanych wyjątków w metodzie doInBackground AsyncTask, która nie wymaga kopiowania i wklejania kodu takiego jak powyżej dla każdej nowej definicji AsyncTask?

Dzięki!

UPDATE

Oto wzorzec projektowy Kiedyś, po patrząc ściślej na source of AsyncTask

import java.io.File; 

import android.content.Context; 
import android.os.AsyncTask; 
import android.os.Environment; 
import android.util.Log; 

public abstract class LoggingAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> { 

    protected void setupUnhandledExceptionLogging(Context context) { 
     try { 
      File crashLogDirectory = new File(Environment.getExternalStorageDirectory().getCanonicalPath() + Constants.CrashLogDirectory); 
      crashLogDirectory.mkdirs(); 

      Thread.setDefaultUncaughtExceptionHandler(new RemoteUploadExceptionHandler(
        context, crashLogDirectory.getCanonicalPath())); 
     } catch (Exception e) { 
      if (MyActivity.WARN) Log.e(ScruffActivity.TAG, "Exception setting up exception handler! " + e.toString()); 
     } 

    } 
} 

potem określić swoje zadania w następujący sposób:

private class MyTask extends LoggingAsyncTask<Void, Void, HashMap<String, Object>> { 
    protected HashMap<String, Object> doInBackground(Void... args) { 
     this.setupUnhandledExceptionLogging(MyActivity.this.mContext); 
     // do work 
     return myHashMap; 
    } 
} 

Oczywiście TWOJEJ Zadanie może wykonać wszelkie niezbędne parametry z tym wzorcem. To Ty definiujesz RemoteUploadExceptionHandler, aby wykonać niezbędne rejestrowanie/przesyłanie.

+0

mam akceptowane we wszystkich sprawach, dla których czułem, że był dobrym rozwiązaniem ... – esilver

Odpowiedz

3

Nie chciałbym iść tak daleko, jak na to wzorzec projektowy zadzwonić, ale po prostu zapisz doInBackground() i zainicjuj i/lub złap wyjątki, jeśli to konieczne.

public abstract class AsyncTaskWrapper<Params, Progress, Result> extends 
     AsyncTask<Params, Progress, Result> { 

    protected Exception error; 

    protected Result doInBackground(Params... params) { 
     try { 
      init(); 

      return doRealWork(params); 
     } catch (Exception e) { 
      error = e; 

      Log.e("TAG", e.getMessage(), e); 

      return null; 
     } 
    } 

    protected abstract void init(); 

    protected abstract Result doRealWork(Params... params); 
} 
+1

Argh, byłem tylko trafienie przedstawienia! +1 –

+0

Czy to działałoby dla dowolnej arbitralnej kombinacji trzech typów AsyncTasks? Czy muszę zdefiniować niestandardowe AsyncTaskWrappers dla każdego typu AsyncTask? To, co chciałbym, to jedno rozwiązanie ogólnego przeznaczenia ... – esilver

+0

Wypróbuj to. Jak widać, jest to sparametryzowana klasa, podobnie jak AsyncTask. Możesz go używać w taki sam sposób jak AsyncTask, po prostu wyprowadź klasy zadań z tej klasy zamiast AsyncTask. –

0

esilver I pułapka wyjątki i zwraca obiekt BoolString, no rzuca wzorzec

//a utility class to signal success or failure, return an error message, and return a useful String value 
//see Try Out in C# 
public final class BoolString { 
public final boolean success; 
public final String err; 
public final String value; 

public BoolString(boolean success, String err, String value){ 
    this.success= success; 
    this.err= err; 
    this.value= value; 
} 
} 

Zastosowanie:

private class MyAsynch extends AsyncTask<String, Void, BoolString>{ 
    protected BoolString doInBackground(String...strings) { // <== DO NOT TOUCH THE UI VIEW HERE  
     return model.tryMyMethod(...); // <== return value BoolString result is sent to onPostExecute 
    }   

protected void onPostExecute(BoolString result){ 
      progress.dismiss(); 
      if (result.success){ 
       ... continue with result.value 
      } 
      else { 
       ..log result.err 
      } 
     } 

// NO THROWS VERSION Helper method 
public BoolString tryMyMethod(...) { 
    try { 
     String value= MyMethod(...); 
     return new BoolString(true,"",value); 
    } 
    catch (Exception e){ 
     return new BoolString(false,e.getMessage(),""); 
    } 
}