acces of local final variable in inner class broken - android

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

Related

Listener Null Object Reference

my onAttach() method assigns the context to the listener, however, my listener is null somehow. How can I fix this problem properly? I hope you can provide me the code with some instructions?
ChooseScreen class which initializes the dialog (In this case nameDialog):
public class ChooseScreen extends AppCompatActivity {
private Button vsFriend;
private Button vsAndroid;
private NameDialog.NameDialogListener listener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_choose_screen);
vsFriend = findViewById(R.id.vsF);
vsAndroid = findViewById(R.id.vsA);
vsFriend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openDialog();
}
});
}
public void openDialog() {
NameDialog nameDialog = new NameDialog();
nameDialog.show(getSupportFragmentManager(), "example");
}
}
NameDialog class with getTexts interface:
public class NameDialog extends AppCompatDialogFragment {
private EditText firstPlayer;
private EditText secondPlayer;
private NameDialogListener listener;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
final View view = inflater.inflate(R.layout.layout_dialog, null);
firstPlayer = view.findViewById(R.id.edit_player1);
secondPlayer = view.findViewById(R.id.edit_player2);
builder.setView(view)
.setTitle("Names")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String player1 = firstPlayer.getText().toString();
String player2 = secondPlayer.getText().toString();
listener.getTexts(player1, player2);
// Intent intent = new Intent(NameDialog.this.getActivity(), Game.class);
// startActivity(intent);
}
});
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try{
listener = (NameDialogListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "must implement");
}
}
public interface NameDialogListener {
void getTexts(String player1, String player2);
}
}
Game class which implements NameDialogListener and overrides the interface method(getTexts):
public class Game extends AppCompatActivity implements
NameDialog.NameDialogListener {
private TextView player1Name;
private TextView player2Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
player1Name = findViewById(R.id.player1TextView);
player2Name = findViewById(R.id.player2TextView);
}
#Override
public void getTexts(String player1, String player2) {
player1Name.setText(player1);
player2Name.setText(player2);
}
}
Error: If I don't use try-catch block, the error will be NullPointerException because listener is null!
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.user.tictactoe, PID: 30462
java.lang.ClassCastException: com.example.user.tictactoe.ChooseScreen#1a0a489must implement
at com.example.user.tictactoe.NameDialog.onAttach(NameDialog.java:62)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1372)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1759)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1827)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:797)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2596)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2383)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2338)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2245)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:703)
at android.os.Handler.handleCallback(Handler.java:751)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6776)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1518)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)
When you attach your Fragment you attempt to get a Listener from your ChoooseScreen Activity. That Activity does not implement NameDialogListener, so you get a ClassCastException. In your examples you show another Activity, Game that does implement the listener, however any activity you add your Fragment in will need to implement the listener to work with your onAttach() code.
Short answer: if you want to show the Fragment in ChooseScreen, your code requires ChooseScreen to implement NameDialogListener.
onAttach will get the context of your parent activity. when you open your Dialog from ChooseScreen activity, the parent is ChooseScreen. The interface callback will be given to ChooseScreen itself. Then what you need to do is to call Intent with player1Name and player2Name.
Anyways I will share the code for you.
Your ChooseScreen
public class ChooseScreen extends AppCompatActivity implements NameDialog.NameDialogListener {
private Button vsFriend;
private Button vsAndroid;
private NameDialog.NameDialogListener listener;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_choose_screen);
vsFriend = findViewById(R.id.vsF);
vsAndroid = findViewById(R.id.vsA);
vsFriend.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openDialog();
}
});
}
public void openDialog() {
NameDialog nameDialog = new NameDialog();
nameDialog.show(getSupportFragmentManager(), "example");
}
#Override
public void getTexts(String player1, String player2) {
Intent intent = new Intent(this, Game.class);
intent.putExtra("PLAYER_ONE", player1);
intent.putExtra("PLAYER_TWO", player2);
startActivity(intent);
}
}
Your NameDialog
public class NameDialog extends AppCompatDialogFragment {
private EditText firstPlayer;
private EditText secondPlayer;
private NameDialogListener listener;
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
LayoutInflater inflater = getActivity().getLayoutInflater();
final View view = inflater.inflate(R.layout.layout_dialog, null);
firstPlayer = view.findViewById(R.id.edit_player1);
secondPlayer = view.findViewById(R.id.edit_player2);
builder.setView(view)
.setTitle("Names")
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
String player1 = firstPlayer.getText().toString();
String player2 = secondPlayer.getText().toString();
listener.getTexts(player1, player2);
//TODO you can simply use below code and comment listener.getTexts();
// Intent intent = new Intent(NameDialog.this.getActivity(), Game.class);
// intent.putExtra("PLAYER_ONE", player1);
// intent.putExtra("PLAYER_TWO", player2);
// startActivity(intent);
}
});
return builder.create();
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (NameDialogListener) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() + "must implement");
}
}
public interface NameDialogListener {
void getTexts(String player1, String player2);
}
}
Your Game
public class Game extends AppCompatActivity
/* implements NameDialog.NameDialogListener*/ {
private TextView player1Name;
private TextView player2Name;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
player1Name = findViewById(R.id.player1TextView);
player2Name = findViewById(R.id.player2TextView);
player1Name.setText(
getIntent().getStringExtra("PLAYER_ONE"));
player2Name.setText(
getIntent().getStringExtra("PLAYER_TWO"));
}
// #Override
// public void getTexts(String player1, String player2) {
// }
}
Try this and let me know...

Calling a method from Fragment inside my class (AsyncTask class to be specific) [duplicate]

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

Activity objects persisting in memory even after calling finish and making the references null

I am making a retrofit enqueue call from SplashActivity and passing data to next activity via bundles.Even after explicitly calling finish on splash activity it still has 48 references in retained heap as seen in MAT.
The app in general is also taking a lot of memory in the background. I debugged and found that my activity's onDestroy() method is getting called, but why are the objects still persistent in the memory? Is it somehow related to the data being passed by reference instead of value? I've been trying to search around the web but with hardly any luck. Please point me if I'm looking in the wrong direction here.
Here's a snapshot of my Splash Activity-
public class SplashActivity extends AppCompatActivity {
private String TAG = SplashActivity.class.getSimpleName();
List<Sport> mSportsList;
List<Event> mEventsList;
List<Carousel> mCarouselList;
WatchOnApiService mWatchOnApiService;
#BindString(R.string.package_name)
String mPackageName;
ProgressBar mProgressBar;
AlertDialog.Builder alertDialogBuilder;
AlertDialog alertDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
ButterKnife.bind(this);
MobileAds.initialize(getApplicationContext(), "ca-app-pub-8433136449848959~7585529227");
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mProgressBar.getIndeterminateDrawable().setColorFilter(Color.WHITE, PorterDuff.Mode.MULTIPLY);
}
#Override
protected void onResume() {
super.onResume();
getSportsAndEventsAndCarousel();
}
private void getSportsAndEventsAndCarousel() {
mProgressBar.setVisibility(View.VISIBLE);
WatchOnApiService mWatchOnApiService = RetrofitFactory.getRetrofit().create(WatchOnApiService.class);
final Call<WatchOnSportsEventsCarousel> mCall = mWatchOnApiService.getAllSportsAndEventsAndCarousel(TimeZone.getDefault().getID());
mCall.enqueue(new Callback<WatchOnSportsEventsCarousel>() {
#Override
public void onResponse(final Response<WatchOnSportsEventsCarousel> response, Retrofit retrofit)
{
if (response.isSuccess()) {
mProgressBar.setVisibility(View.INVISIBLE);
if (Float.parseFloat(BuildConfig.VERSION_NAME) < Float.parseFloat(response.body().getAndroidLatestVersion())) {
if (response.body().getAndroidForceUpdate().equalsIgnoreCase("1")) {
showForceUpdateDialog();
} else {
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(SplashActivity.this);
alertDialogBuilder.setTitle("WatchOn");
alertDialogBuilder.setMessage("WatchOn just got better.Would you like to upgrade ?");
alertDialogBuilder.setPositiveButton("Upgrade",
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int arg1) {
dialog.dismiss();
try { SplashActivity.this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + mPackageName)));
} catch (android.content.ActivityNotFoundException anfe) {
SplashActivity.this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + mPackageName)));
}
}
});
alertDialogBuilder.setNegativeButton("Dismiss", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
beginFlow(response);
}
});
AlertDialog alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
} else {
beginFlow(response);
}
}
//Response not received something went wrong
else {
showAlertDialogNoResponse();
}
}
private void beginFlow(final Response<WatchOnSportsEventsCarousel> response) {
Bundle mBundle = new Bundle();
mSportsList = CodeUtils.convertSportsListToLocalTime(response.body().getData().getSports());
Parcelable wrappedSports = Parcels.wrap(new ArrayList<>(mSportsList));
mBundle.putParcelable(AppConstants.SPORTS_LIST, wrappedSports);
mEventsList = CodeUtils.convertEventsListToLocalTime(response.body().getData().getEvents());
Parcelable wrappedEvents = Parcels.wrap(new ArrayList<>(mEventsList));
mBundle.putParcelable(AppConstants.EVENTS_LIST, wrappedEvents);
mCarouselList = response.body().getData().getCarousels();
Parcelable wrappedCarousels = Parcels.wrap(new ArrayList<>(mCarouselList));
mBundle.putParcelable(AppConstants.CAROUSELS_LIST, wrappedCarousels);
if ((response.body().getLiveSponsors() == 1)) {
mBundle.putBoolean(AppConstants.LIVE_SPONSORS_AVAILABLE, true);
} else {
mBundle.putBoolean(AppConstants.LIVE_SPONSORS_AVAILABLE, false);
}
Intent i = new Intent(SplashActivity.this, SelectSportEventActivity.class);
i.putExtras(mBundle);
mSportsList = null;
mEventsList = null;
mCarouselList = null;
startActivity(i);
SplashActivity.this.finish();
}
#Override
public void onFailure(Throwable t) {
showAlertDialogInternetFail();
alertDialogBuilder.setNegativeButton("Retry", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
getSportsAndEventsAndCarousel();
dialog.dismiss();
}
});
alertDialog = alertDialogBuilder.create();
alertDialog.show();
}
});
}
#Override
protected void onDestroy() {
ButterKnife.unbind(this);
Log.d(TAG, "onDestroy: " + mSportsList + mEventsList + mCarouselList);
alertDialog = null;
super.onDestroy();
}
}

Why does not this AlertDialog show?

I created an AlertDialog :
public class MessageDialogView extends AlertDialog {
private Context ctxt;
private View contenu, titleBar;
#SuppressLint("NewApi")
public MessageDialogView(Context context, LayoutInflater inflater) {
super(context);
ctxt = context;
contenu = inflater.inflate(R.layout.msg_dialog, null);
titleBar = inflater.inflate(R.layout.custom_dialog_title, null);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setCustomTitle(titleBar);
setView(contenu, 0, 0, 0, 0);
setButton(DialogInterface.BUTTON_POSITIVE, ctxt.getResources().getString(R.string.button_ok), new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
}
public void setTitre(String titre) {
if (titre != null)
((TextView)titleBar.findViewById(R.id.titre)).setText(titre);
}
public void setMsg(String text){
if (text != null)
((TextView)contenu.findViewById(R.id.msgText)).setText(text);
}
}
The xml layout are very simple ( not necessary to copy their code here :) )
When I try to show the AlertDialog then nothing is showing : just the screen is darkened !
public class SyncActivity extends Activity {
private RadioButton webVersMobile = null;
private MessageDialogView dlg = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.syncro);
webVersMobile = (RadioButton) findViewById(R.id.webMobile);
dlg = new MessageDialogView(SyncActivity.this, getLayoutInflater());
}
...
public void displayError(String msg) {
dlg.setTitre(getString(R.string.titreErrMsgBox));
dlg.setMsg(msg);
dlg.show();
}
...
}
I call the dialog like this :
private class RequestTask extends AsyncTask<String, Void, String> {
...
#Override
protected String doInBackground(String... s_url) {
...
}
#Override
protected void onPostExecute(String result) {
if (error) {
displayError(result);
} else {
}
}
private void displayError(String msg) {
dlg.setTitre(getString(R.string.titreErrMsgBox));
dlg.setMsg(msg);
dlg.show();
}
}
So what is wrong in my code ?
You forgot to call show() method to display the dialog.
dlg = new MessageDialogView(SyncActivity.this, getLayoutInflater());
After this line write dlg.show(); in onCreate() method.
Ok , I found that the reason of my error is that I implemented the onCreate method. When I removed the implementation then the Dialog is shown :)
public class MessageDialogView extends AlertDialog {
private View contenu, titleBar;
#SuppressLint("InlinedApi")
public MessageDialogView(Context context, LayoutInflater inflater) {
super(context, AlertDialog.THEME_HOLO_DARK);
contenu = inflater.inflate(R.layout.msg_dialog, null);
titleBar = inflater.inflate(R.layout.custom_dialog_title, null);
setCustomTitle(titleBar);
setView(contenu, 0, 0, 0, 0);
setButton(DialogInterface.BUTTON_POSITIVE, context.getResources().getString(R.string.button_ok), new OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
}
public void setTitre(String titre) {
if (titre != null)
((TextView)titleBar.findViewById(R.id.titre)).setText(titre);
}
public void setMsg(String text){
if (text != null)
((TextView)contenu.findViewById(R.id.msgText)).setText(text);
}
}

Android: Callback AsyncTask to Fragment(Not Activity)

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

Categories

Resources