Fragments/Activities auto-cancel their requests when they're destroyed. Also, fixes a ComposeActivity crash that can occur when a media preview doesn't load.
This commit is contained in:
parent
f391538984
commit
0662f35b96
|
@ -37,7 +37,7 @@ import java.util.List;
|
|||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
|
||||
public class AccountFragment extends Fragment implements AccountActionListener {
|
||||
public class AccountFragment extends BaseFragment implements AccountActionListener {
|
||||
private static final String TAG = "Account"; // logging tag
|
||||
|
||||
private Call<List<Account>> listCall;
|
||||
|
@ -176,25 +176,23 @@ public class AccountFragment extends Fragment implements AccountActionListener {
|
|||
default:
|
||||
case FOLLOWS: {
|
||||
listCall = api.accountFollowing(accountId, fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case FOLLOWERS: {
|
||||
listCall = api.accountFollowers(accountId, fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case BLOCKS: {
|
||||
listCall = api.blocks(fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case MUTES: {
|
||||
listCall = api.mutes(fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
callList.add(listCall);
|
||||
listCall.enqueue(cb);
|
||||
}
|
||||
|
||||
private void fetchAccounts() {
|
||||
|
@ -264,11 +262,14 @@ public class AccountFragment extends Fragment implements AccountActionListener {
|
|||
}
|
||||
};
|
||||
|
||||
Call<Relationship> call;
|
||||
if (!block) {
|
||||
api.unblockAccount(id).enqueue(cb);
|
||||
call = api.unblockAccount(id);
|
||||
} else {
|
||||
api.blockAccount(id).enqueue(cb);
|
||||
call = api.blockAccount(id);
|
||||
}
|
||||
callList.add(call);
|
||||
call.enqueue(cb);
|
||||
}
|
||||
|
||||
private void onBlockSuccess(boolean blocked, int position) {
|
||||
|
|
|
@ -34,6 +34,7 @@ import com.google.gson.GsonBuilder;
|
|||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.Dispatcher;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
|
@ -48,6 +49,7 @@ import retrofit2.converter.gson.GsonConverterFactory;
|
|||
public class BaseActivity extends AppCompatActivity {
|
||||
protected MastodonAPI mastodonAPI;
|
||||
protected TuskyAPI tuskyAPI;
|
||||
protected Dispatcher mastodonApiDispatcher;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
|
@ -64,6 +66,12 @@ public class BaseActivity extends AppCompatActivity {
|
|||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
mastodonApiDispatcher.cancelAll();
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
super.finish();
|
||||
|
@ -95,6 +103,8 @@ public class BaseActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
protected void createMastodonAPI() {
|
||||
mastodonApiDispatcher = new Dispatcher();
|
||||
|
||||
OkHttpClient okHttpClient = new OkHttpClient.Builder()
|
||||
.addInterceptor(new Interceptor() {
|
||||
@Override
|
||||
|
@ -111,6 +121,7 @@ public class BaseActivity extends AppCompatActivity {
|
|||
return chain.proceed(newRequest);
|
||||
}
|
||||
})
|
||||
.dispatcher(mastodonApiDispatcher)
|
||||
.build();
|
||||
|
||||
Gson gson = new GsonBuilder()
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/* Copyright 2017 Andrew Dawson
|
||||
*
|
||||
* This file is part of Tusky.
|
||||
*
|
||||
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with Tusky. If not, see
|
||||
* <http://www.gnu.org/licenses/>. */
|
||||
|
||||
package com.keylesspalace.tusky;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import retrofit2.Call;
|
||||
|
||||
public class BaseFragment extends Fragment {
|
||||
protected List<Call> callList;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
callList = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
for (Call call : callList) {
|
||||
call.cancel();
|
||||
}
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
|
@ -72,7 +72,6 @@ import android.widget.TextView;
|
|||
|
||||
import com.keylesspalace.tusky.entity.Media;
|
||||
import com.keylesspalace.tusky.entity.Status;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
|
@ -822,12 +821,8 @@ public class ComposeActivity extends BaseActivity {
|
|||
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(side, side);
|
||||
layoutParams.setMargins(margin, 0, margin, marginBottom);
|
||||
view.setLayoutParams(layoutParams);
|
||||
|
||||
Picasso.with(this)
|
||||
.load(uri)
|
||||
.resize(side, side)
|
||||
.centerCrop()
|
||||
.into(view);
|
||||
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||
view.setImageBitmap(preview);
|
||||
|
||||
view.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
|
@ -986,20 +981,24 @@ public class ComposeActivity extends BaseActivity {
|
|||
waitForMediaLatch.countDown();
|
||||
} else {
|
||||
Log.d(TAG, "Upload request failed. " + response.message());
|
||||
onUploadFailure(item);
|
||||
onUploadFailure(item, call.isCanceled());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<Media> call, Throwable t) {
|
||||
Log.d(TAG, t.getMessage());
|
||||
onUploadFailure(item);
|
||||
onUploadFailure(item, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void onUploadFailure(QueuedMedia item) {
|
||||
displayTransientError(R.string.error_media_upload_sending);
|
||||
private void onUploadFailure(QueuedMedia item, boolean isCanceled) {
|
||||
if (isCanceled) {
|
||||
/* if the upload was voluntarily cancelled, such as if the user clicked on it to remove
|
||||
* it from the queue, then don't display this error message. */
|
||||
displayTransientError(R.string.error_media_upload_sending);
|
||||
}
|
||||
if (finishingUploadDialog != null) {
|
||||
finishingUploadDialog.cancel();
|
||||
}
|
||||
|
@ -1059,7 +1058,7 @@ public class ComposeActivity extends BaseActivity {
|
|||
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
|
||||
retriever.setDataSource(this, uri);
|
||||
Bitmap source = retriever.getFrameAtTime();
|
||||
Bitmap bitmap = ThumbnailUtils.extractThumbnail(source, 96, 96);
|
||||
Bitmap bitmap = ThumbnailUtils.extractThumbnail(source, 128, 128);
|
||||
source.recycle();
|
||||
addMediaToQueue(QueuedMedia.Type.VIDEO, bitmap, uri, mediaSize);
|
||||
break;
|
||||
|
@ -1073,7 +1072,7 @@ public class ComposeActivity extends BaseActivity {
|
|||
return;
|
||||
}
|
||||
Bitmap source = BitmapFactory.decodeStream(stream);
|
||||
Bitmap bitmap = ThumbnailUtils.extractThumbnail(source, 96, 96);
|
||||
Bitmap bitmap = ThumbnailUtils.extractThumbnail(source, 128, 128);
|
||||
source.recycle();
|
||||
try {
|
||||
if (stream != null) {
|
||||
|
|
|
@ -161,6 +161,7 @@ public class NotificationsFragment extends SFragment implements
|
|||
onFetchNotificationsFailure((Exception) t);
|
||||
}
|
||||
});
|
||||
callList.add(listCall);
|
||||
}
|
||||
|
||||
private void sendFetchNotificationsRequest() {
|
||||
|
|
|
@ -19,9 +19,9 @@ import android.content.Context;
|
|||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
@ -45,7 +45,7 @@ import retrofit2.Callback;
|
|||
* adapters. I feel like the profile pages and thread viewer, which I haven't made yet, will also
|
||||
* overlap functionality. So, I'm momentarily leaving it and hopefully working on those will clear
|
||||
* up what needs to be where. */
|
||||
public class SFragment extends Fragment {
|
||||
public class SFragment extends BaseFragment {
|
||||
protected String loggedInAccountId;
|
||||
protected String loggedInUsername;
|
||||
|
||||
|
@ -103,11 +103,14 @@ public class SFragment extends Fragment {
|
|||
}
|
||||
};
|
||||
|
||||
Call<Status> call;
|
||||
if (reblog) {
|
||||
getApi().reblogStatus(id).enqueue(cb);
|
||||
call = getApi().reblogStatus(id);
|
||||
} else {
|
||||
getApi().unreblogStatus(id).enqueue(cb);
|
||||
call = getApi().unreblogStatus(id);
|
||||
}
|
||||
call.enqueue(cb);
|
||||
callList.add(call);
|
||||
}
|
||||
|
||||
protected void favourite(final Status status, final boolean favourite,
|
||||
|
@ -134,15 +137,19 @@ public class SFragment extends Fragment {
|
|||
}
|
||||
};
|
||||
|
||||
Call<Status> call;
|
||||
if (favourite) {
|
||||
getApi().favouriteStatus(id).enqueue(cb);
|
||||
call = getApi().favouriteStatus(id);
|
||||
} else {
|
||||
getApi().unfavouriteStatus(id).enqueue(cb);
|
||||
call = getApi().unfavouriteStatus(id);
|
||||
}
|
||||
call.enqueue(cb);
|
||||
callList.add(call);
|
||||
}
|
||||
|
||||
private void block(String id) {
|
||||
getApi().blockAccount(id).enqueue(new Callback<Relationship>() {
|
||||
Call<Relationship> call = getApi().blockAccount(id);
|
||||
call.enqueue(new Callback<Relationship>() {
|
||||
@Override
|
||||
public void onResponse(Call<Relationship> call, retrofit2.Response<Relationship> response) {
|
||||
|
||||
|
@ -153,10 +160,12 @@ public class SFragment extends Fragment {
|
|||
|
||||
}
|
||||
});
|
||||
callList.add(call);
|
||||
}
|
||||
|
||||
private void delete(String id) {
|
||||
getApi().deleteStatus(id).enqueue(new Callback<ResponseBody>() {
|
||||
Call<ResponseBody> call = getApi().deleteStatus(id);
|
||||
call.enqueue(new Callback<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
|
||||
|
||||
|
@ -167,6 +176,7 @@ public class SFragment extends Fragment {
|
|||
|
||||
}
|
||||
});
|
||||
callList.add(call);
|
||||
}
|
||||
|
||||
protected void more(Status status, View view, final AdapterItemRemover adapter,
|
||||
|
|
|
@ -193,30 +193,27 @@ public class TimelineFragment extends SFragment implements
|
|||
default:
|
||||
case HOME: {
|
||||
listCall = api.homeTimeline(fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case PUBLIC: {
|
||||
listCall = api.publicTimeline(null, fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case TAG: {
|
||||
listCall = api.hashtagTimeline(hashtagOrId, null, fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case USER: {
|
||||
listCall = api.accountStatuses(hashtagOrId, fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case FAVOURITES: {
|
||||
listCall = api.favourites(fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
callList.add(listCall);
|
||||
listCall.enqueue(cb);
|
||||
}
|
||||
|
||||
private void sendFetchTimelineRequest() {
|
||||
|
|
|
@ -79,7 +79,8 @@ public class ViewThreadFragment extends SFragment implements StatusActionListene
|
|||
private void sendStatusRequest(final String id) {
|
||||
MastodonAPI api = ((BaseActivity) getActivity()).mastodonAPI;
|
||||
|
||||
api.status(id).enqueue(new Callback<Status>() {
|
||||
Call<Status> call = api.status(id);
|
||||
call.enqueue(new Callback<Status>() {
|
||||
@Override
|
||||
public void onResponse(Call<Status> call, retrofit2.Response<Status> response) {
|
||||
if (response.isSuccessful()) {
|
||||
|
@ -95,12 +96,14 @@ public class ViewThreadFragment extends SFragment implements StatusActionListene
|
|||
onThreadRequestFailure(id);
|
||||
}
|
||||
});
|
||||
callList.add(call);
|
||||
}
|
||||
|
||||
private void sendThreadRequest(final String id) {
|
||||
MastodonAPI api = ((BaseActivity) getActivity()).mastodonAPI;
|
||||
|
||||
api.statusContext(id).enqueue(new Callback<StatusContext>() {
|
||||
Call<StatusContext> call = api.statusContext(id);
|
||||
call.enqueue(new Callback<StatusContext>() {
|
||||
@Override
|
||||
public void onResponse(Call<StatusContext> call, retrofit2.Response<StatusContext> response) {
|
||||
if (response.isSuccessful()) {
|
||||
|
@ -118,6 +121,7 @@ public class ViewThreadFragment extends SFragment implements StatusActionListene
|
|||
onThreadRequestFailure(id);
|
||||
}
|
||||
});
|
||||
callList.add(call);
|
||||
}
|
||||
|
||||
private void onThreadRequestFailure(final String id) {
|
||||
|
|
Loading…
Reference in New Issue