2013-03-07 17 views
8

Ich versuche Callback zwischen AsyncTask und Fragment zu implementieren, kann aber keine korrekten Informationen finden, wie es geht. Das Problem ist, dass alle Callback-Implementierungen zwischen Aktivität und asynctask sind, aber ich brauche zwischen Fragment und asynctask. Könnte mir jemand kleines Arbeitsbeispiel geben, wie man es ohne Aktivität umsetzt. Meine Aktionsstruktur: Fragmentaufruf DialogFragment -> etwas auswählen und Serveranforderung an asynchrone Aufgabe senden -> asynchrone Aufgabe alles verarbeiten und Sicht und einige Variablen aktualisieren. Mein Hauptproblem ist, dass ich PrepareData() nur einmal in onCreate aufrufen und wenn ich zwischen anderen Fragments gehe und zurückkomme, sehe ich alte Daten. Das heißt, es ist nicht genug, um nur die Ansicht in onPost von asynctask zu aktualisieren. Es wird gut sein, Rückruf zu haben, der die ganzen Variablen aktualisiert.Android: Callback AsyncTask zu Fragment (keine Aktivität)

public class TermsAndConditionsFragment extends SherlockFragment implements OnClickListener, OnTouchListener, OnItemClickListener, onTaskListener { 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    fm = getSherlockActivity().getSupportFragmentManager(); 


    prepareData(); 
} 

public void prepareData() { 
    termsAndConditionsM = new TermsAndConditionsManager(getSherlockActivity()); 
    termsAndConditions = termsAndConditionsM.getTermsAndConditions(); 

    if (termsAndConditions != null) { 
       int totalPayments = Integer.valueOf(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS)); 
     if (totalPayments > 0) { 
      paymentsData = termsAndConditionsM.getpayments(); 

      if (paymentsData != null) { 

       payments = new ArrayList<Payment>(); 

       for (int i = 1; i <= totalPayments; i++) { 
        paymentValues = new Payment(); 
        paymentValues.setPaymentID(Integer.valueOf(paymentsData.get(ServerAPI.PAYMENT_NO + "_" + i))); 
        paymentValues.setPaymentDate(paymentsData.get(ServerAPI.PAYMENT_DATE + "_" + i)); 
        paymentValues.setPaymentTotalAmount(paymentsData.get(ServerAPI.PAYMENT_TOTAL + "_" + i)); 
        payments.add(paymentValues); 
       } 
      } 
     } 
    } 
} 

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

    rootView = init(inflater, container); 

    if (payments != null || termsAndConditions != null) 
     updateTermsAndConditionsView(); 

    return rootView; 
} 

private View init(LayoutInflater inflater, ViewGroup container) { 
    rootView = inflater.inflate(R.layout.fragment_terms_and_conditions, container, false); 

    ... 
    return rootView; 
} 

public void updateTermsAndConditionsView() { 
    etHowMuch.setText("£" + termsAndConditions.get(ServerAPI.AMOUNT_OF_CREDIT)); 
    etForHowLong.setText(Helpers.ConvertDays2Date(Integer.valueOf(termsAndConditions.get(ServerAPI.TERM_OF_AGREEMENT_IN_DAYS)))); 

    PaymentAdapter adapter = new PaymentAdapter(getSherlockActivity(), R.layout.custom_loan_item, payments); 
    lvPayments.setAdapter(adapter); 

    tvNoOfPayments.setText(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS)); 
    tvFirstPayment.setText(termsAndConditions.get(ServerAPI.FIRST_PAYMENT_DATE)); 
    tvTotalRepayable.setText("£" + termsAndConditions.get(ServerAPI.TOTAL_REPAYABLE)); 
} 

@Override 
public void onClick(View v) { 
    ft = fm.beginTransaction(); 

    howMuch = etHowMuch.getText().toString(); 
    forHowLong = etForHowLong.getText().toString(); 

    switch (v.getId()) { 
     case R.id.etHowMuch: 
      f = new NumberPaymentsPickerFragment(); 
      args = new Bundle(); 
      args.putInt(Const.HOW_MUCH, Integer.valueOf(howMuch.replace("£", ""))); 
      args.putDouble(ServerAPI.PAYMENT_STEP, Const.PAYMENT_STEP); 
      args.putString(Const.STATE, ServerAPI.TERMS_AND_CONDITIONS); 
      f.setArguments(args); 
      f.setTargetFragment(this, DIALOG_FRAGMENT); 
      f.show(getActivity().getSupportFragmentManager(), Const.HOW_MUCH); 
      break; 
     case R.id.etForHowLong: 
      f = new NumberPaymentsPickerFragment(); 
      args = new Bundle(); 
      args.putInt(Const.FOR_HOW_LONG, Integer.valueOf(Helpers.ConvertDate2Days(forHowLong))); 
      args.putDouble(ServerAPI.PAYMENT_STEP, Const.PAYMENT_STEP); 
      args.putString(Const.STATE, ServerAPI.TERMS_AND_CONDITIONS); 
      f.setArguments(args); 
      f.setTargetFragment(this, DIALOG_FRAGMENT); 
      f.show(getActivity().getSupportFragmentManager(), Const.FOR_HOW_LONG); 
      break; 
     case R.id.tvPersonalDetails: 
      sfm.saveCurFragment(ServerAPI.PERSONAL_DETAILS, 0); 
      ft.replace(android.R.id.content, new PersonalDetailsFragment(), ServerAPI.PERSONAL_DETAILS).addToBackStack(null).commit(); 
      break; 
     case R.id.tvAgreementDetails: 
      sfm.saveCurFragment(ServerAPI.AGREEMENT_DETAILS, 0); 
      ft.replace(android.R.id.content, new AgreementDetailsFragment(), ServerAPI.AGREEMENT_DETAILS).addToBackStack(null).commit(); 
      break; 
     case R.id.bApply: 

      break; 
    } 

@Override 
public void onUpdateData() { 
    Log.d(TAG, "Update data"); 

} 

} 

DialogFragment:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    Bundle args = getArguments(); 

    ... 
} 

public Dialog onCreateDialog(Bundle savedInstanceState) { 

    ... 

     return createDialog(v, R.string.for_how_long, etHowMuch, etForHowLong, etPromotionCode); 
    } 
    return null; 
} 
private Dialog createDialog(View view, int titleResID, final EditText howMuchField, final EditText forHowLongField, final EditText promotionCodeField) { 
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); 
    builder.setTitle(titleResID); 
    builder.setView(view); 
    builder.setPositiveButton(R.string.set, new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int id) { 

      doShowProgress(); 

     } 

     private void doShowProgress() { 


      ExecuteServerTaskBackground task = new 
        ExecuteServerTaskBackground(getActivity()); 
       task.action = ServerAPI.GET_TERMS_AND_CONDITIONS; 
       onTaskListener listener = new onTaskListener() { 

       @Override 
       public void onUpdateData() { 
        Log.d(TAG, "Updaaate"); 

       } 
      }; 
      task.setListener(listener); 
      task.args = args; 
      task.execute(); 
     } 

    }).setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int id) { 
      dialog.cancel(); 
     } 
    }); 
    return builder.create(); 
} 

AsyncTask:

onTaskListener mListener; 

public interface onTaskListener { 
    void onUpdateData(); 
} 

public void setListener(onTaskListener listener){ 
    mListener = listener; 
} 
public ExecuteServerTaskBackground(Activity activity) { 
    this.mActivity = activity; 
    this.mContext = activity.getApplicationContext(); 
} 

@Override 
protected void onPreExecute() { 
    pb = (ProgressBar) mActivity.findViewById(R.id.progressBar1); 
    pb.setVisibility(View.VISIBLE); 
} 

@Override 
protected Void doInBackground(Void... params) { 
    ServerAPI server = new ServerAPI(mContext); 
    if (!args.isEmpty()) 
     server.serverRequest(action, args); 
    else 
     server.serverRequest(action, null); 
    return null; 
} 

@Override 
protected void onPostExecute(Void result) { 
mListener.onUpdateData(); 

//There is I just update view but how to update whole variables throughtout callback?   
//    tvNoOfPayments = (TextView) mActivity.findViewById(R.id.tvNoOfPaymentsValue); 
//    tvFirstPayment = (TextView) mActivity.findViewById(R.id.tvFirstPaymentValue); 
//    tvTotalRepayable = (TextView) mActivity.findViewById(R.id.tvTotalRepayableValue); 
// 
//    lvPayments = (ListView) mActivity.findViewById(R.id.lvData); 
// 
//    termsConditionsM = new TermsAndConditionsManager(mContext); 
// 
//    termsAndConditions = termsConditionsM.getTermsAndConditions(); 
// 
//    int totalPayments = Integer.valueOf(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS)); 
// 
//    if (totalPayments > 0) { 
//     if (termsAndConditions != null) { 
//      tvNoOfPayments.setText(termsAndConditions.get(ServerAPI.NO_OF_PAYMENTS)); 
//      tvFirstPayment.setText(termsAndConditions.get(ServerAPI.FIRST_PAYMENT_DATE)); 
//      tvTotalRepayable.setText("£" + termsAndConditions.get(ServerAPI.TOTAL_REPAYABLE)); 
//     } 
// 
//     paymentsData = termsConditionsM.getpayments(); 
// 
//     if (paymentsData != null) { 
//      Log.d(TAG, paymentsData.toString()); 
// 
//      payments = new ArrayList<Payment>(); 
// 
//      for (int i = 1; i <= totalPayments; i++) { 
//       paymentValues = new Payment(); 
//       paymentValues.setPaymentID(Integer.valueOf(paymentsData.get(ServerAPI.PAYMENT_NO + "_" + i))); 
//       paymentValues.setPaymentDate(paymentsData.get(ServerAPI.PAYMENT_DATE + "_" + i)); 
//       paymentValues.setPaymentTotalAmount(paymentsData.get(ServerAPI.PAYMENT_TOTAL + "_" + i)); 
//       payments.add(paymentValues); 
//      } 
// 
//      PaymentAdapter adapter = new PaymentAdapter(mContext, R.layout.custom_loan_item, payments); 
//      lvPayments.setAdapter(adapter); 
//     } 
    //    

    } 

    pb.setVisibility(View.GONE); 
    super.onPostExecute(result); 
} 

Antwort

25

Ohne Ihren Code in Betracht zu ziehen ich die wesentlichsten Posten werde einen funktionellen Rückruf zu machen.


TestFragment:

public class TestFragment extends Fragment { 

    /* Skipping most code and I will only show you the most essential. */  
    private void methodThatStartsTheAsyncTask() { 
     TestAsyncTask testAsyncTask = new TestAsyncTask(new FragmentCallback() { 

      @Override 
      public void onTaskDone() { 
       methodThatDoesSomethingWhenTaskIsDone(); 
      } 
     }); 

     testAsyncTask.execute(); 
    } 

    private void methodThatDoesSomethingWhenTaskIsDone() { 
     /* Magic! */ 
    } 

    public interface FragmentCallback { 
     public void onTaskDone(); 
    } 
} 

TestAsyncTask:

public class TestAsyncTask extends AsyncTask<Void, Void, Void> { 
    private FragmentCallback mFragmentCallback; 

    public TestAsyncTask(FragmentCallback fragmentCallback) { 
     mFragmentCallback = fragmentCallback; 
    } 

    @Override 
    protected Void doInBackground(Void... params) { 
     /* Do your thing. */ 
     return null; 
    } 

    @Override 
    protected void onPostExecute(Void result) { 
     mFragmentCallback.onTaskDone(); 
    } 
} 
+0

Das ist, was ich jetzt habe. Und dieser Teil funktioniert, aber ich möchte Nachricht nicht an der gleichen Stelle, wo AsyncTask aufgerufen wurde. Meine Struktur ist MainFragment (hier möchte ich Nachricht fangen) -> DialogFragment (asynctask aufrufen) -> async Aufgabe (Verarbeitung und Ergebnis in min-Fragment zurückgeben). Jetzt funktioniert der Callback normalerweise nur für die Verbindung zwischen DialogFragment und AsyncTask, aber wie kann man das Ergebnis direkt an mainFragment senden? – user1376885

+0

Entweder, wenn es nur während zwei Callbacks möglich ist (1 Callback - AsyncTask -> DialogFragment, 2 Callback - DialogFragment-> MainFragment) und wie man Listener an DialogFragment sendet. Es ist nicht möglich, setLIstener wie in AsyncTask zu verwenden. – user1376885

+0

@ user1376885 Speichern Sie das Ergebnis in einer Datenbank oder laden Sie etwas, das nicht gespeichert werden kann? Eine gute Vorgehensweise besteht darin, einen "zustandslosen" Ansatz beizubehalten, was bedeutet, dass Sie keine Inhalte direkt zwischen Fragmenten oder Aktivitäten senden dürfen. Sie möchten es in einer Datenbank speichern und beim Start des Fragments/der Aktivität lesen Sie die Datenbank und laden die Werte und präsentieren sie. Also, was machst du in deiner AsyncTask? Es sieht so aus, als könnten Sie es in einer Datenbank speichern. –

Verwandte Themen