2013-03-07 92 views
8

我想实现AsyncTask和片段之间的回调,但无法找到正确的信息如何做到这一点。问题是所有的回调实现都是在activity和asynctask之间,但我需要在fragment和asynctask之间。有人能给我一个小实例,说明如何在没有活动的情况下实施它。 我的动作结构:片段调用DialogFragment - >选择一些东西并发送服务器请求到异步任务 - >异步任务处理所有内容并更新视图和一些变量。我的主要问题是,我只在onCreate中调用prepareData()一次,当我在其他片段之间行走并返回时,我会看到旧数据。也就是说,仅仅更新asynctask的onPost中的视图是不够的。回调会更新整个变量将会很好。Android:回调AsyncTask片段(不活动)

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

回答

25

如果不考虑你的代码考虑,我将发布最重要的,使功能性回调。


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

这正是我现在有。这部分工作正常,但我想在不同的地方调用AsyncTask来捕获消息。我的结构是MainFragment(这里我想捕获消息) - > DialogFragment(调用asynctask) - >异步任务(处理并返回min分片结果)。现在,只有在DialogFragment和AsyncTask之间的连接时,回调才能正常工作,但是如何将结果直接发送到mainFragment? – user1376885 2013-03-07 13:33:52

+0

如果只能在两个回调中执行(1回调 - AsyncTask - > DialogFragment,2回调 - DialogFragment-> MainFragment),那么如何将侦听器发送到DialogFragment。不可能像在AsyncTask中那样使用setLIstener。 – user1376885 2013-03-07 13:34:57

+0

@ user1376885将结果保存到数据库中,还是加载了无法保存的内容?好的做法是保持“无状态”的方式,这意味着你不能直接在碎片或活动之间发送东西。您将希望将其保存到数据库中,并且在Fragment/Activity启动时读取数据库并加载值并呈现。那么,你在AsyncTask中做什么?它看起来像你可以将它保存到数据库。 – 2013-03-07 13:41:49