I am trying to implement callback between AsyncTask and Fragment but cannot find correct info how to do it. The issue is that all callback implementations are between activity and asynctask but I need between fragment and asynctask. Could someone give me small working example how to implement it without activity.
My action structure: Fragment call DialogFragment -> choose something and send server request to async task -> async task process everything and update view and some variables. My main problem is that I call prepareData() only once in onCreate and when I walk between other fragment and returns come back I see old data. That is to say there is not enough to update only view in onPost of asynctask. It will be good to have callback which will update the whole variables.
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);
}
Without taking your code in consideration I will post the most essential to make a functional callback.
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();
}
}
Related
I am creating an android app, where I'll be asking for multiple types of questions using RadioButtons. I don't want to make multiple Activities for these questions. Can anyone please tell me how to do that with a short example, of at least two questions?
You can use multiples fragments... or call the activity itself multiple times...
I did an app like yours and i choose the first method!
This is some fragment of a project that i wrote, and the activity that manipulate it, you will have to change it according to your needs.
Activity
public class CollectActivity extends FragmentActivity {
MyPageAdapter pageAdapter;
NonSwipeableViewPager pager;
SpringIndicator springIndicator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collect);
List<Fragment> fragments = getFragments();
pager = (NonSwipeableViewPager) findViewById(R.id.view_pager);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
PagerModelManager manager = new PagerModelManager();
manager.addCommonFragment(fragments, getTitles());
ModelPagerAdapter adapter = new ModelPagerAdapter(getSupportFragmentManager(), manager);
pager.setAdapter(adapter);
springIndicator = (SpringIndicator) findViewById(R.id.indicator);
springIndicator.setViewPager(pager);
springIndicator.setOnTabClickListener(new TabClickListener() {
#Override
public boolean onTabClick(int position) {
return false;
}
});
}
private List<Fragment> getFragments() {
List<Fragment> fList = new ArrayList<Fragment>();
fList.add(CollectFragment.newInstance("Fragment 1"));
fList.add(CollectFragment.newInstance("Fragment 2"));
fList.add(CollectFragment.newInstance("Fragment 3"));
//add your fragments with a loop
return fList;
}
private List<String> getTitles() {
return Lists.newArrayList("1", "2", "3");
}
public void swipeFragment() {
pager.setCurrentItem(pager.getCurrentItem() + 1);
}
public int getFragment() {
return pager.getCurrentItem();
}
}
Fragment
public class CollectFragment extends Fragment {
private Button openButton;
private Button confirmationCloseButton;
private Button yesRenew;
private Button noRenew;
private BroadcastReceiver udpMessages;
public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";
public static final CollectFragment newInstance(String message) {
CollectFragment f = new CollectFragment();
Bundle bdl = new Bundle(1);
bdl.putString(EXTRA_MESSAGE, message);
f.setArguments(bdl);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String message = getArguments().getString(EXTRA_MESSAGE);
View v = null;
if (message.compareTo("Fragment 1") == 0) {
v = inflater.inflate(R.layout.fragment_collect_open, container, false);
openButton = (Button) v.findViewById(R.id.open_button);
openButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i2 = new Intent();
i2.setComponent(new ComponentName("qira.com.locker", "qira.com.locker.Service.MessageService"));
i2.putExtra("Message", "CONFIRM_LOCKER_1_CLOSED");
getContext().startService(i2);
}
});
}
if (message.compareTo("Fragment 2") == 0) {
v = inflater.inflate(R.layout.fragment_collect_close, container, false);
confirmationCloseButton = (Button) v.findViewById(R.id.confirmation_close_button);
confirmationCloseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i2 = new Intent();
i2.setComponent(new ComponentName("qira.com.locker", "qira.com.locker.Service.MessageService"));
i2.putExtra("Message", "OPEN_LOCKER_1");
getContext().startService(i2);
}
});
}
if (message.compareTo("Fragment 3") == 0) {
v = inflater.inflate(R.layout.fragment_collect_renew, container, false);
yesRenew = (Button) v.findViewById(R.id.yes_button);
noRenew = (Button) v.findViewById(R.id.no_button);
yesRenew.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((CollectActivity) getActivity()).swipeFragment();
}
});
noRenew.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(getContext(), ReserveActivity.class);
startActivity(i);
}
});
}
return v;
}
#Override
public void onResume() {
super.onResume();
udpMessages = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null && intent.getAction().equals("UDP.MESSAGES.COLLECT")) {
if (intent.getExtras().getString("Type").compareTo("OPEN_LOCKER_1-LOCKER_OPENED") == 0) {
if (((CollectActivity) getActivity()).getFragment() != 0) { // onCreateView called twice, dont know why... workaround to solve this problem
((CollectActivity) getActivity()).swipeFragment();
}
}
if (intent.getExtras().getString("Type").compareTo("CONFIRM_LOCKER_1_CLOSED-TRUE") == 0) {
if (((CollectActivity) getActivity()).getFragment() != 1) { // onCreateView called twice, dont know why... workaround to solve this problem
((CollectActivity) getActivity()).swipeFragment();
}
}
}
}
};
getContext().registerReceiver(udpMessages, new IntentFilter("UDP.MESSAGES.COLLECT"));
}
#Override
public void onPause() {
super.onPause();
getContext().unregisterReceiver(udpMessages);
}
#Override
public void onDestroyView() {
super.onDestroyView();
}
}
I am trying to implement callback between AsyncTask and Fragment but cannot find correct info how to do it. The issue is that all callback implementations are between activity and asynctask but I need between fragment and asynctask. Could someone give me small working example how to implement it without activity.
My action structure: Fragment call DialogFragment -> choose something and send server request to async task -> async task process everything and update view and some variables. My main problem is that I call prepareData() only once in onCreate and when I walk between other fragment and returns come back I see old data. That is to say there is not enough to update only view in onPost of asynctask. It will be good to have callback which will update the whole variables.
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);
}
Without taking your code in consideration I will post the most essential to make a functional callback.
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();
}
}
I'm new to android programming. I want to create a custom progress dialog with some textview and button and showing the progress with two progressBar and updating them while sending the files from Asynctask, Also I want it works with minimum API 10. google doc recommend me to use DialogFragment and i do not have any idea how to update the progress bars and textviews that are in that custom layout of my fragmentDialog, when I try to reference a textview or progress bar it throw null exeption
Here is my code
public static class FireMissilesDialogFragment extends DialogFragment {
public FireMissilesDialogFragment(){
}
public static FireMissilesDialogFragment newInstance(String title) {
FireMissilesDialogFragment frag = new FireMissilesDialogFragment();
Bundle args = new Bundle();
args.putString("title", title);
frag.setArguments(args);
return frag;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Use the Builder class for convenient dialog construction
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
// Get the layout inflater
LayoutInflater inflater = this.getActivity().getLayoutInflater();
// Inflate and set the layout for the dialog
// Pass null as the parent view because its going in the dialog layout
View view = inflater.inflate(R.layout.custom_progress, null);
ProgressBar pbCurrent = (ProgressBar) view.findViewById(R.id.current);
builder.setView(view);
builder.setMessage("Fire Missiles")
.setPositiveButton("Fire", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// FIRE ZE MISSILES!
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// User cancelled the dialog
}
});
// Create the AlertDialog object and return it
return builder.create();
}
}
I got a nullExeption here in my main activity when try to reference a view
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button frag = (Button) findViewById(R.id.frag);
frag.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FireMissilesDialogFragment fragment = FireMissilesDialogFragment.newInstance("hi") ;
fragment.getActivity().findViewById(R.id.current);// nullExeption here
// downloadAsync as = new downloadAsync();
// as.execute();
}
});
I didn't see much question and example about that, did I go all the way wrong and should pick another way to achieve my point??!!
Edit :
I'm trying to create something like this
thanks in advance
I can not do a full explanation but I can leave an example and then hopefully you can figure out a way to incorporate the things you need.
The DialogFragment with an AsyncTask and a Progress bar:
public class LoadHydrantsToMapTaskFragment extends DialogFragment {
public static final String TAG = LoadHydrantsToMapTaskFragment.class
.getSimpleName();
public interface LoadHydrantsToMapTaskCallback {
void onPreExecute(int maxProgress);
void onProgressUpdate(int progress);
void onCancelled();
void onPostExecute();
}
private LoadHydrantsToMapTask mTask;
// private ProgressBar mProgressBar;
private List<HydrantHolder> mHydrants;
private GoogleMap map;
public static LoadHydrantsToMapTaskFragment newInstance(
List<HydrantHolder> hydrants, GoogleMap map) {
LoadHydrantsToMapTaskFragment taskFragment = new LoadHydrantsToMapTaskFragment();
taskFragment.mHydrants = hydrants;
taskFragment.map = map;
return taskFragment;
}
#Override public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.dialog_progress_task, container);
mProgressBar = (ProgressBar) view.findViewById(R.id.progressBar);
mProgressBar.setProgress(0);
mProgressBar.setMax(mHydrants.size());
getDialog().setTitle(getActivity().getString(R.string.adding_hydrants));
// This dialog can't be canceled by pressing the back key.
getDialog().setCancelable(false);
getDialog().setCanceledOnTouchOutside(false);
return view;
}
/**
* This method will only be called once when the retained Fragment is first
* created.
*/
#Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(SherlockDialogFragment.STYLE_NORMAL, R.style.TuriosDialog);
// Retain this fragment across configuration changes.
setRetainInstance(true);
mTask = new LoadHydrantsToMapTask(mHydrants);
mTask.setCallback(new LoadHydrantsToMapTaskCallback() {
#Override public void onPreExecute(int maxProgress) {
}
#Override public void onProgressUpdate(int progress) {
mProgressBar.setProgress(progress);
}
#Override public void onPostExecute() {
if (isResumed())
dismiss();
mTask = null;
}
#Override public void onCancelled() {
if (isResumed())
dismiss();
mTask = null;
}
});
mTask.execute();
}
#Override public void onResume() {
super.onResume();
// This is a little hacky, but we will see if the task has finished
// while we weren't
// in this activity, and then we can dismiss ourselves.
if (mTask == null)
dismiss();
}
#Override public void onDetach() {
super.onDetach();
}
// This is to work around what is apparently a bug. If you don't have it
// here the dialog will be dismissed on rotation, so tell it not to dismiss.
#Override public void onDestroyView() {
if (getDialog() != null && getRetainInstance())
getDialog().setDismissMessage(null);
super.onDestroyView();
}
// Also when we are dismissed we need to cancel the task.
#Override public void onDismiss(DialogInterface dialog) {
super.onDismiss(dialog);
// If true, the thread is interrupted immediately, which may do bad
// things.
// If false, it guarantees a result is never returned (onPostExecute()
// isn't called)
// but you have to repeatedly call isCancelled() in your
// doInBackground()
// function to check if it should exit. For some tasks that might not be
// feasible.
if (mTask != null)
mTask.cancel(false);
}
private class LoadHydrantsToMapTask extends
AsyncTask<Void, Integer, List<MarkerOptions>> {
// Before running code in separate thread
List<HydrantHolder> mHydrants;
LoadHydrantsToMapTaskCallback mLoadHydrantsToMapTaskCallback;
public LoadHydrantsToMapTask(List<HydrantHolder> hydrants) {
this.mHydrants = hydrants;
}
public void setCallback(
LoadHydrantsToMapTaskCallback loadHydrantsToMapTaskCallback) {
this.mLoadHydrantsToMapTaskCallback = loadHydrantsToMapTaskCallback;
}
#Override protected void onPreExecute() {
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onPreExecute(mHydrants.size());
}
}
// The code to be executed in a background thread.
#Override protected List<MarkerOptions> doInBackground(Void... arg) {
List<MarkerOptions> markers = new ArrayList<MarkerOptions>();
for (HydrantHolder hydrant : mHydrants) {
final String hydrant_type = hydrant.getHydrantType();
final String hydrant_icon_path = hydrant.getIconPath();
double latitude = hydrant.getLatitude();
double longitude = hydrant.getLongitude();
final LatLng position = new LatLng(latitude, longitude);
final String address = hydrant.getAddress();
final String addressNumber = hydrant.getAddressNumber();
final String addressremark = hydrant.getAddressRemark();
final String remark = hydrant.getRemark();
// Log.d(TAG, hydrant.toString());
BitmapDescriptor icon = BitmapDescriptorFactory
.defaultMarker(BitmapDescriptorFactory.HUE_RED);
if (!hydrant_icon_path.isEmpty()) {
File iconfile = new File(hydrant_icon_path);
if (iconfile.exists()) {
BitmapDescriptor loaded_icon = BitmapDescriptorFactory
.fromPath(hydrant_icon_path);
if (loaded_icon != null) {
icon = loaded_icon;
} else {
Log.e(TAG, "loaded_icon was null");
}
} else {
Log.e(TAG, "iconfile did not exist: "
+ hydrant_icon_path);
}
} else {
Log.e(TAG, "iconpath was empty on hydrant type: "
+ hydrant_type);
}
StringBuffer snippet = new StringBuffer();
if (!address.isEmpty())
snippet.append("\n" + address + " " + addressNumber);
if (addressremark.isEmpty())
snippet.append("\n" + addressremark);
if (!remark.isEmpty())
snippet.append("\n" + remark);
markers.add(new MarkerOptions().position(position)
.title(hydrant_type).snippet(snippet.toString())
.icon(icon));
publishProgress(markers.size());
}
return markers;
}
// Update the progress
#Override protected void onProgressUpdate(Integer... values) {
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onProgressUpdate(values[0]);
}
}
#Override protected void onCancelled() {
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onCancelled();
}
}
// after executing the code in the thread
#Override protected void onPostExecute(List<MarkerOptions> markers) {
for (MarkerOptions marker : markers) {
if (marker != null && map != null)
map.addMarker(marker);
}
if (mLoadHydrantsToMapTaskCallback != null) {
mLoadHydrantsToMapTaskCallback.onPostExecute();
}
}
}
}
My dialog_progress_task layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical" >
<ProgressBar
android:id="#+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:maxHeight="10dip"
android:minHeight="10dip"
android:progress="0"
android:progressDrawable="#drawable/progress_orange" />
</LinearLayout>
And finally the code I use to add it:
#Override public void loadHydrantsToMap(List<HydrantHolder> hydrants,
GoogleMap map) {
LoadHydrantsToMapTaskFragment loadHydrantsFragment;
if (fm != null) {
FragmentTransaction ft = fm.beginTransaction();
loadHydrantsFragment = (LoadHydrantsToMapTaskFragment) fm
.findFragmentByTag(LoadHydrantsToMapTaskFragment.TAG);
if (loadHydrantsFragment != null) {
Log.i("Attatching LoadHydrantsToMapTaskFragment");
ft.attach(loadHydrantsFragment);
} else {
loadHydrantsFragment = LoadHydrantsToMapTaskFragment
.newInstance(hydrants, map);
Log.i("Adding new LoadHydrantsToMapTaskFragment");
ft.add(loadHydrantsFragment, LoadHydrantsToMapTaskFragment.TAG);
}
ft.commit();
}
}
I'm stuck with communication between activity and fragment using interface. I have created activity with child fragment. I wanna do some stuff with continuous thread defined in activity and during that thread when I'm getting some result at that time I wanna trigger to child fragment to do something.
My Container Activity
public class MySpaceActivity extends BaseDrawerActivity {
private OnSetLastSeenListener mListner;
public static Thread mThread = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
super.setHeaders(Const.MY_SPACE);
super.setSubmenus(Const.MY_SPACE,
Utils.getSubmenuList(Const.MY_SPACE, MySpaceActivity.this),
submenuBean);
// super.attachFragment(submenuBean);
}
#Override
public void setHeaderSubMenu(SubmenuBean subMenuBean) {
// txt_submenu.setText(subMenuBean.getSubmenu_name());
this.submenuBean = subMenuBean;
Log.print("::::: setHeaderSubMenu ::::");
super.attachFragment(submenuBean);
}
public void setsubFragment(SubmenuBean subMenuBean) {
this.submenuBean = subMenuBean;
super.attachSubFragment(submenuBean);
}
#Override
public void onBackPressed() {
super.onBackPressed();
popLastFragment();
}
private void popLastFragment() {
if (super.getNumberOfChilds() > 1) {
super.popSubFragment();
} else {
finish();
}
}
#Override
protected Fragment getFragement() {
StudentsFragment fragment = new StudentsFragment(Const.MY_SPACE,
getSubmenubean());
return fragment;
}
public SubmenuBean getSubmenubean() {
return submenuBean;
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
mThread = new Thread(new CountDownTimer(MySpaceActivity.this));
mThread.start();
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
if (mThread.isAlive()) {
mThread.interrupt();
mThread = null;
}
}
public void updateLastSeen(){
Log.print("::::::Call Interface::::::");
mListner.updateLastSeen();
}
class CountDownTimer implements Runnable {
private Context mContext;
private JSONObject mJsonObject;
private JSONArray mJsonArray;
public CountDownTimer(Context mContext) {
this.mContext = mContext;
}
// #Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
HttpChatLastSeen mChat = new HttpChatLastSeen();
mJsonObject = mChat.Http_ChatLastSeen(mContext);
String mResult = mJsonObject.getString("Result");
if (mResult.equalsIgnoreCase(String
.valueOf(Const.RESULT_OK))) {
mJsonArray = mJsonObject.getJSONArray("UserData");
for (int i = 0; i < mJsonArray.length(); i++) {
mJsonObject = mJsonArray.getJSONObject(i);
new DbStudentMasterBll(mContext).update(
"last_seen", mJsonObject
.getString("LastSeen"), Integer
.parseInt(mJsonObject
.getString("UserId")));
}
} else {
Log.print("MY LAST SEEN Response : "
+ mJsonObject.toString());
}
updateLastSeen();
Thread.sleep(15000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
Log.print("ChatLastSeenThread : ", e.getMessage());
}
}
}
}
}
My Child Fragment With Interface :
public class StudentsFragment extends Fragment implements OnSetLastSeenListener{
TextView txt_submenu;
ListView list_students;
SubmenuBean submenuBean;
int Mainmenu;
MySpaceActivity mMySpaceActivity;
ArrayList<DbStudentMasterBean> studentsList;
StudentsAdapter mAdapter = null;
OnSetLastSeenListener mListner;
public StudentsFragment() {
super();
}
public StudentsFragment(int Mainmenu, SubmenuBean submenuBean) {
this.submenuBean = submenuBean;
this.Mainmenu = Mainmenu;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_students, container,
false);
mMySpaceActivity = (MySpaceActivity) getActivity();
txt_submenu = (TextView) view.findViewById(R.id.txt_submenu);
txt_submenu.setText(submenuBean.getSubmenu_name());
txt_submenu.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mMySpaceActivity.openDrawer();
}
});
list_students = (ListView) view.findViewById(R.id.list_colleagues);
studentsList = new DbStudentMasterBll(getActivity()).getAllRecords();
mAdapter = new StudentsAdapter(getActivity(), studentsList, handler);
list_students.setAdapter(mAdapter);
list_students.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
DbStudentMasterBean bean = (DbStudentMasterBean) parent
.getAdapter().getItem(position);
Message msg = new Message();
msg.what = CHAT;
msg.obj = bean;
handler.sendMessage(msg);
}
});
return view;
}
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case CHAT:
submenuBean.setTag(VIEWCHATSTUDENT);
DbStudentMasterBean bean = (DbStudentMasterBean) msg.obj;
mMySpaceActivity.setsubFragment(submenuBean);
break;
}
};
};
#Override
public void updateLastSeen() {
// TODO Auto-generated method stub
Log.print("!!!!!!!!!Refresh Adapter!!!!!!!!!!!");
mAdapter.notifyDataSetChanged();
}
}
My Interface :
public interface OnSetLastSeenListener {
public void updateLastSeen();
}
So I have implemented interface OnSetLastSeenListener with my child fragment StudentsFragment . Now I'm calling method of tht interface updateLastSeen() from my container activity with thread. But it is not getting trigger to child fragment where I have implemented interface. So I don't know whether it is good way to communicate or not? Let me take your help to suggest on this solution or best way to communicate from child fragment to parent activity.
Thanks,
It is better to use interface when you want to communicate something from Fragment to Activity and not vice versa.
In your case, you can directly call the method in Fragment from Activity through fragment object. No need to use interface.
Something like this (For static fragments)
StudentsFragment fragment = (StudentsFragment) getFragmentManager()
.findFragmentById(R.id.fragmentid);
if (fragment != null && fragment.isInLayout()) {
fragment.updateLastSeen();
}
For dynamic fragment you can use the fragment object directly.
I got a method in which server-client communication is done "onClick" therefor i create a anonymous OnClickListener, and I want to publish a toast if the communication was successfull or not.
To do this I need the Acitivity in which context to publish the toast, and as I externalized the method, it must be given as a "this" argument to the Activity. But as I am inside an anonymous inner class I cannot access the this pointer of the Acitivity, and even though I stored it in a local final variable
private final Activity activity = this;
#Override
public void onCreate(Bundle savedInstanceState) {
lastResult = null;
super.onCreate(savedInstanceState);
setLayout(R.layout.main);
qrscan = (Button) findViewById(R.id.qrcodescan);
qrscan.setOnClickListener( new View.OnClickListener() {
public void onClick(View view) {
initiateScan(activity);
}
}
);
}
private AlertDialog initiateSend(Activity activity) {
if(lastResult != null) {
String[] arr = lastResult.content.split("/");
AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
String[] args = Util.filterString(arr,this);
downloadDialog.setTitle(args[0]);
downloadDialog.setMessage("Auftragsnummer:" + args[1]);
downloadDialog.setPositiveButton(getString(R.string.ja), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
try {
String send = lastResult.content;
send += "/uid/" + R.id.username + "/cid/" + R.id.password;
String result = Util.send(send);
//toaster(send);
Util.toaster(result,activity);
if(!(result.equals("OK") || result.equals("ok") || result.equals("Ok")))
throw new Exception("Bad Server Answer");
Util.toaster("Communication erfolgreich",activity);
} catch(Exception ex) {
ex.printStackTrace();
Util.toaster("Communication nicht erfolgreich",activity);
}
}
});
downloadDialog.setNegativeButton(getString(R.string.nein), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {}
});
return downloadDialog.show();
}
return null;
}
Any clue what i messed up?
declare variable before onCreate() like this
public class HelloAndroid extends Activity {
Activity activity = this; // declare here
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
EDITED
Activity mainActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setLayout(R.layout.main);
mainActivity = this;
lastResult = null;
qrscan = (Button) findViewById(R.id.qrcodescan);
qrscan.setOnClickListener( new View.OnClickListener() {
public void onClick(View view) {
initiateScan(mainActivity);
}
}
);
}
private AlertDialog initiateSend(final Activity activity) {
if(lastResult != null) {
String[] arr = lastResult.content.split("/");
AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
String[] args = Util.filterString(arr,this);
downloadDialog.setTitle(args[0]);
downloadDialog.setMessage("Auftragsnummer:" + args[1]);
downloadDialog.setPositiveButton(getString(R.string.ja), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialogInterface, int i) {
try {
String send = lastResult.content;
send += "/uid/" + R.id.username + "/cid/" + R.id.password;
String result = Util.send(send);
//toaster(send);
Util.toaster(result,activity);
if(!(result.equals("OK") || result.equals("ok") || result.equals("Ok")))
throw new Exception("Bad Server Answer");
Util.toaster("Communication erfolgreich",activity);
} catch(Exception ex) {
ex.printStackTrace();
Util.toaster("Communication nicht erfolgreich",activity);
}
}
});
downloadDialog.setNegativeButton(getString(R.string.nein), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {}
});
return downloadDialog.show();
}
return null;
}