Sto lavorando su un'app per smartphone / tablet, utilizzando un solo APK e caricando le risorse in base alle dimensioni dello schermo, la scelta migliore per il design sembrava utilizzare i frammenti tramite l'ACL.
Questa app ha funzionato bene fino ad ora essendo basata solo sull'attività. Questa è una classe fittizia di come gestisco AsyncTasks e ProgressDialogs nelle attività in modo che funzionino anche quando lo schermo viene ruotato o si verifica una modifica della configurazione durante la comunicazione.
Non cambierò il manifest per evitare di ricreare l'attività, ci sono molte ragioni per cui non voglio farlo, ma principalmente perché i documenti ufficiali dicono che non è raccomandato e sono riuscito senza di esso fino ad ora, quindi per favore non lo consiglio itinerario.
public class Login extends Activity {
static ProgressDialog pd;
AsyncTask<String, Void, Boolean> asyncLoginThread;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.login);
//SETUP UI OBJECTS
restoreAsyncTask();
}
@Override
public Object onRetainNonConfigurationInstance() {
if (pd != null) pd.dismiss();
if (asyncLoginThread != null) return (asyncLoginThread);
return super.onRetainNonConfigurationInstance();
}
private void restoreAsyncTask();() {
pd = new ProgressDialog(Login.this);
if (getLastNonConfigurationInstance() != null) {
asyncLoginThread = (AsyncTask<String, Void, Boolean>) getLastNonConfigurationInstance();
if (asyncLoginThread != null) {
if (!(asyncLoginThread.getStatus()
.equals(AsyncTask.Status.FINISHED))) {
showProgressDialog();
}
}
}
}
public class LoginThread extends AsyncTask<String, Void, Boolean> {
@Override
protected Boolean doInBackground(String... args) {
try {
//Connect to WS, recieve a JSON/XML Response
//Place it somewhere I can use it.
} catch (Exception e) {
return true;
}
return true;
}
protected void onPostExecute(Boolean result) {
if (result) {
pd.dismiss();
//Handle the response. Either deny entry or launch new Login Succesful Activity
}
}
}
}
Questo codice funziona bene, ho circa 10.000 utenti senza lamentele, quindi mi è sembrato logico copiare questa logica nel nuovo Fragment Based Design, ma, ovviamente, non funziona.
Ecco il LoginFragment:
public class LoginFragment extends Fragment {
FragmentActivity parentActivity;
static ProgressDialog pd;
AsyncTask<String, Void, Boolean> asyncLoginThread;
public interface OnLoginSuccessfulListener {
public void onLoginSuccessful(GlobalContainer globalContainer);
}
public void onSaveInstanceState(Bundle outState){
super.onSaveInstanceState(outState);
//Save some stuff for the UI State
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setRetainInstance(true);
//If I setRetainInstance(true), savedInstanceState is always null. Besides that, when loading UI State, a NPE is thrown when looking for UI Objects.
parentActivity = getActivity();
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
loginSuccessfulListener = (OnLoginSuccessfulListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnLoginSuccessfulListener");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
RelativeLayout loginLayout = (RelativeLayout) inflater.inflate(R.layout.login, container, false);
return loginLayout;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
//SETUP UI OBJECTS
if(savedInstanceState != null){
//Reload UI state. Im doing this properly, keeping the content of the UI objects, not the object it self to avoid memory leaks.
}
}
public class LoginThread extends AsyncTask<String, Void, Boolean> {
@Override
protected Boolean doInBackground(String... args) {
try {
//Connect to WS, recieve a JSON/XML Response
//Place it somewhere I can use it.
} catch (Exception e) {
return true;
}
return true;
}
protected void onPostExecute(Boolean result) {
if (result) {
pd.dismiss();
//Handle the response. Either deny entry or launch new Login Succesful Activity
}
}
}
}
}
Non posso usarlo onRetainNonConfigurationInstance()
poiché deve essere chiamato dall'attività e non dal frammento, lo stesso vale per getLastNonConfigurationInstance()
. Ho letto alcune domande simili qui senza risposta.
Capisco che potrebbe richiedere un po 'di lavoro per organizzare correttamente questa roba in frammenti, detto questo, vorrei mantenere la stessa logica di progettazione di base.
Quale sarebbe il modo corretto per mantenere l'AsyncTask durante una modifica della configurazione e, se è ancora in esecuzione, mostrare un progressDialog, tenendo in considerazione che l'AsyncTask è una classe interna al Fragment ed è il Fragment stesso che richiama l'AsyncTask.execute ()?