Skip to content

Commit

Permalink
Fix memory leaks in example app (#865)
Browse files Browse the repository at this point in the history
**Summary**
- Create `ActivitySourceCallback` to help with memory
  handling
- Refactor and clean-up classes in example app to fix
  memory leaks as identified by LeakCanary
- Call `CompositeSubscription#unsubscribe()` in
  `Activity#onDestroy()` where missing

**Motivation**
ANDROID-349

**Testing**
Ran example app
  • Loading branch information
mshafrir-stripe committed Apr 11, 2019
1 parent 7208c62 commit ab91036
Show file tree
Hide file tree
Showing 19 changed files with 236 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ protected void onCreate(Bundle savedInstanceState) {
@Override
public void onStringResponse(String string) {
if (string.startsWith("Error: ")) {
mErrorDialogHandler.showError(string);
mErrorDialogHandler.show(string);
}
}
}));
Expand All @@ -68,7 +68,7 @@ public void onCustomerRetrieved(@NonNull Customer customer) {
public void onError(int httpCode, @Nullable String errorMessage,
@Nullable StripeError stripeError) {
mSelectSourceButton.setEnabled(false);
mErrorDialogHandler.showError(errorMessage);
mErrorDialogHandler.show(errorMessage);
mProgressBar.setVisibility(View.INVISIBLE);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ public class PaymentIntentActivity extends AppCompatActivity {
private static final String TAG = PaymentIntentActivity.class.getName();

private static final String RETURN_URL = "stripe://payment_intent_return";

@NonNull private final CompositeSubscription mCompositeSubscription =
new CompositeSubscription();
private ProgressDialogController mProgressDialogController;
private ErrorDialogHandler mErrorDialogHandler;
private CompositeSubscription mCompositeSubscription;
private Stripe mStripe;
private StripeService mStripeService;
private String mClientSecret;
Expand All @@ -60,16 +62,15 @@ public class PaymentIntentActivity extends AppCompatActivity {
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_payment_intent_demo);
Button createPaymentIntent = findViewById(R.id.btn_create_payment_intent);
final Button createPaymentIntent = findViewById(R.id.btn_create_payment_intent);
mRetrievePaymentIntent = findViewById(R.id.btn_retrieve_payment_intent);
mConfirmPaymentIntent = findViewById(R.id.btn_confirm_payment_intent);
mPaymentIntentValue = findViewById(R.id.payment_intent_value);
mCardInputWidget = findViewById(R.id.card_input_widget);
mProgressDialogController =
new ProgressDialogController(getSupportFragmentManager());

mProgressDialogController = new ProgressDialogController(getSupportFragmentManager(),
getResources());
mErrorDialogHandler = new ErrorDialogHandler(getSupportFragmentManager());
mCompositeSubscription = new CompositeSubscription();
mStripe = new Stripe(getApplicationContext());
Retrofit retrofit = RetrofitFactory.getInstance();
mStripeService = retrofit.create(StripeService.class);
Expand Down Expand Up @@ -98,6 +99,13 @@ public void onClick(View v) {
});
}

@Override
protected void onDestroy() {
mCompositeSubscription.unsubscribe();
super.onDestroy();
}

@NonNull
private Map<String, Object> createPaymentIntentParams() {
final Map<String, Object> params = new HashMap<>();
params.put("allowed_source_types[]", "card");
Expand All @@ -113,14 +121,13 @@ void createPaymentIntent() {
.doOnSubscribe(new Action0() {
@Override
public void call() {
mProgressDialogController.setMessageResource(R.string.creating_payment_intent);
mProgressDialogController.startProgress();
mProgressDialogController.show(R.string.creating_payment_intent);
}
})
.doOnUnsubscribe(new Action0() {
@Override
public void call() {
mProgressDialogController.finishProgress();
mProgressDialogController.dismiss();
}
})
.subscribe(
Expand All @@ -143,7 +150,7 @@ public void call(ResponseBody responseBody) {
new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
mErrorDialogHandler.showError(throwable.getLocalizedMessage());
mErrorDialogHandler.show(throwable.getLocalizedMessage());
}
}
);
Expand All @@ -165,14 +172,13 @@ public PaymentIntent call() throws Exception {
.doOnSubscribe(new Action0() {
@Override
public void call() {
mProgressDialogController.setMessageResource(R.string.retrieving_payment_intent);
mProgressDialogController.startProgress();
mProgressDialogController.show(R.string.retrieving_payment_intent);
}
})
.doOnUnsubscribe(new Action0() {
@Override
public void call() {
mProgressDialogController.finishProgress();
mProgressDialogController.dismiss();
}
})
.observeOn(AndroidSchedulers.mainThread()).subscribe(
Expand Down Expand Up @@ -216,14 +222,13 @@ public PaymentIntent call() throws Exception {
.doOnSubscribe(new Action0() {
@Override
public void call() {
mProgressDialogController.setMessageResource(R.string.confirming_payment_intent);
mProgressDialogController.startProgress();
mProgressDialogController.show(R.string.confirming_payment_intent);
}
})
.doOnUnsubscribe(new Action0() {
@Override
public void call() {
mProgressDialogController.finishProgress();
mProgressDialogController.dismiss();
}
})
.subscribe(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.stripe.example.activity;

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;
Expand Down Expand Up @@ -37,7 +38,9 @@ public class PaymentMultilineActivity extends AppCompatActivity {
ErrorDialogHandler mErrorDialogHandler;

CardMultilineWidget mCardMultilineWidget;
CompositeSubscription mCompositeSubscription;

@NonNull private final CompositeSubscription mCompositeSubscription =
new CompositeSubscription();

private SimpleAdapter mSimpleAdapter;
private List<Map<String, String>> mCardSources= new ArrayList<>();
Expand All @@ -47,11 +50,10 @@ protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_payment_multiline);

mCompositeSubscription = new CompositeSubscription();
mCardMultilineWidget = findViewById(R.id.card_multiline_widget);

mProgressDialogController =
new ProgressDialogController(getSupportFragmentManager());
mProgressDialogController = new ProgressDialogController(getSupportFragmentManager(),
getResources());

mErrorDialogHandler = new ErrorDialogHandler(getSupportFragmentManager());

Expand Down Expand Up @@ -100,14 +102,14 @@ public Source call() throws Exception {
new Action0() {
@Override
public void call() {
mProgressDialogController.startProgress();
mProgressDialogController.show(R.string.progressMessage);
}
})
.doOnUnsubscribe(
new Action0() {
@Override
public void call() {
mProgressDialogController.finishProgress();
mProgressDialogController.dismiss();
}
})
.subscribe(
Expand All @@ -120,7 +122,7 @@ public void call(Source source) {
new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
mErrorDialogHandler.showError(throwable.getLocalizedMessage());
mErrorDialogHandler.show(throwable.getLocalizedMessage());
}
}));
}
Expand All @@ -139,4 +141,9 @@ private void addToList(@Nullable Source source) {
mSimpleAdapter.notifyDataSetChanged();
}

@Override
protected void onDestroy() {
mCompositeSubscription.unsubscribe();
super.onDestroy();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ private void setupCustomerSession() {
@Override
public void onStringResponse(String string) {
if (string.startsWith("Error: ")) {
mErrorDialogHandler.showError(string);
mErrorDialogHandler.show(string);
}
}
}));
Expand All @@ -142,7 +142,7 @@ public void onError(int httpCode, @Nullable String errorMessage,
mCustomer = null;
mSelectPaymentButton.setEnabled(false);
mSelectShippingButton.setEnabled(false);
mErrorDialogHandler.showError(errorMessage);
mErrorDialogHandler.show(errorMessage);
mProgressBar.setVisibility(View.INVISIBLE);
}
});
Expand Down Expand Up @@ -287,7 +287,7 @@ public void onError(int errorCode, @Nullable String errorMessage) {
return;
}

activity.mErrorDialogHandler.showError(errorMessage);
activity.mErrorDialogHandler.show(errorMessage);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@ public class RedirectActivity extends AppCompatActivity {
private static final String QUERY_CLIENT_SECRET = "client_secret";
private static final String QUERY_SOURCE_ID = "source";

@NonNull private final CompositeSubscription mCompositeSubscription =
new CompositeSubscription();

private CardInputWidget mCardInputWidget;
private CompositeSubscription mCompositeSubscription;
private RedirectAdapter mRedirectAdapter;
private ErrorDialogHandler mErrorDialogHandler;
private RedirectDialogController mRedirectDialogController;
Expand All @@ -58,10 +60,10 @@ protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_polling);

mCompositeSubscription = new CompositeSubscription();
mCardInputWidget = findViewById(R.id.card_widget_three_d);
mErrorDialogHandler = new ErrorDialogHandler(this.getSupportFragmentManager());
mProgressDialogController = new ProgressDialogController(this.getSupportFragmentManager());
mProgressDialogController = new ProgressDialogController(this.getSupportFragmentManager(),
getResources());
mRedirectDialogController = new RedirectDialogController(this);
mStripe = new Stripe(getApplicationContext());

Expand Down Expand Up @@ -113,8 +115,8 @@ protected void onNewIntent(Intent intent) {

@Override
protected void onDestroy() {
super.onDestroy();
mCompositeSubscription.unsubscribe();
super.onDestroy();
}

void beginSequence() {
Expand Down Expand Up @@ -149,8 +151,7 @@ public Source call() throws Exception {
.doOnSubscribe(new Action0() {
@Override
public void call() {
mProgressDialogController.setMessageResource(R.string.createSource);
mProgressDialogController.startProgress();
mProgressDialogController.show(R.string.createSource);
}
})
.subscribe(
Expand All @@ -176,15 +177,15 @@ public void call(Source source) {
// The card Source can be used to create a 3DS Source
createThreeDSecureSource(source.getId());
} else {
mProgressDialogController.finishProgress();
mProgressDialogController.dismiss();
}

}
},
new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
mErrorDialogHandler.showError(throwable.getMessage());
mErrorDialogHandler.show(throwable.getMessage());
}
}
));
Expand Down Expand Up @@ -221,7 +222,7 @@ public Source call() throws Exception {
.doOnUnsubscribe(new Action0() {
@Override
public void call() {
mProgressDialogController.finishProgress();
mProgressDialogController.dismiss();
}
})
.subscribe(
Expand All @@ -238,7 +239,7 @@ public void call(Source source) {
new Action1<Throwable>() {
@Override
public void call(Throwable throwable) {
mErrorDialogHandler.showError(throwable.getMessage());
mErrorDialogHandler.show(throwable.getMessage());
}
}
));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.stripe.android.model.Card;
import com.stripe.android.model.Token;
import com.stripe.android.view.CardInputWidget;
import com.stripe.example.R;

/**
* Logic needed to create tokens using the {@link android.os.AsyncTask} methods included in the
Expand All @@ -21,7 +22,6 @@ public class AsyncTaskTokenController {

@NonNull private final Stripe mStripe;
@NonNull private final ErrorDialogHandler mErrorDialogHandler;
@NonNull private final ListViewController mOutputListController;
@NonNull private final ProgressDialogController mProgressDialogController;

@Nullable private CardInputWidget mCardInputWidget;
Expand All @@ -30,19 +30,22 @@ public AsyncTaskTokenController(
@NonNull Button button,
@NonNull CardInputWidget cardInputWidget,
@NonNull Context context,
@NonNull ErrorDialogHandler errorDialogHandler,
@NonNull ListViewController outputListController,
@NonNull ProgressDialogController progressDialogController) {
@NonNull final ErrorDialogHandler errorDialogHandler,
@NonNull final ListViewController outputListController,
@NonNull final ProgressDialogController progressDialogController) {
mCardInputWidget = cardInputWidget;
mStripe = new Stripe(context);
mErrorDialogHandler = errorDialogHandler;
mProgressDialogController = progressDialogController;
mOutputListController = outputListController;

button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
saveCard();
saveCard(new TokenCallbackImpl(
errorDialogHandler,
outputListController,
progressDialogController
));
}
});
}
Expand All @@ -51,25 +54,39 @@ public void detach() {
mCardInputWidget = null;
}

private void saveCard() {
final Card cardToSave = mCardInputWidget.getCard();
private void saveCard(@NonNull TokenCallback tokenCallback) {
final Card cardToSave = mCardInputWidget != null ? mCardInputWidget.getCard() : null;
if (cardToSave == null) {
mErrorDialogHandler.showError("Invalid Card Data");
mErrorDialogHandler.show("Invalid Card Data");
return;
}
mProgressDialogController.startProgress();
mProgressDialogController.show(R.string.progressMessage);
mStripe.createToken(
cardToSave,
PaymentConfiguration.getInstance().getPublishableKey(),
new TokenCallback() {
public void onSuccess(@NonNull Token token) {
mOutputListController.addToList(token);
mProgressDialogController.finishProgress();
}
public void onError(@NonNull Exception error) {
mErrorDialogHandler.showError(error.getLocalizedMessage());
mProgressDialogController.finishProgress();
}
});
tokenCallback);
}

private static class TokenCallbackImpl implements TokenCallback {
@NonNull private final ErrorDialogHandler mErrorDialogHandler;
@NonNull private final ListViewController mOutputListController;
@NonNull private final ProgressDialogController mProgressDialogController;

private TokenCallbackImpl(@NonNull ErrorDialogHandler errorDialogHandler,
@NonNull ListViewController outputListController,
@NonNull ProgressDialogController progressDialogController) {
this.mErrorDialogHandler = errorDialogHandler;
this.mOutputListController = outputListController;
this.mProgressDialogController = progressDialogController;
}

public void onSuccess(@NonNull Token token) {
mOutputListController.addToList(token);
mProgressDialogController.dismiss();
}
public void onError(@NonNull Exception error) {
mErrorDialogHandler.show(error.getLocalizedMessage());
mProgressDialogController.dismiss();
}
}
}

0 comments on commit ab91036

Please sign in to comment.