Use viewholder for populating contributions list (#2306)

* Use viewholder for populatiing contributions list

* Fix codacy issues

* Remove unused code
This commit is contained in:
Vivek Maskara 2019-01-30 15:36:15 +05:30 committed by neslihanturan
parent 2ba6ed622f
commit 35f1e84ff1
6 changed files with 187 additions and 123 deletions

View file

@ -1,35 +1,96 @@
package fr.free.nrw.commons.contributions;
import android.content.Context;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import fr.free.nrw.commons.MediaWikiImageView;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.ViewHolder;
import fr.free.nrw.commons.contributions.model.DisplayableContribution;
class ContributionViewHolder {
final MediaWikiImageView imageView;
final TextView titleView;
final TextView stateView;
final TextView seqNumView;
final ProgressBar progressView;
final ImageButton retryButton;
final ImageButton cancelButton;
final LinearLayout failedImageOptions;
int position;
class ContributionViewHolder implements ViewHolder<DisplayableContribution> {
@BindView(R.id.contributionImage) MediaWikiImageView imageView;
@BindView(R.id.contributionTitle) TextView titleView;
@BindView(R.id.contributionState) TextView stateView;
@BindView(R.id.contributionSequenceNumber) TextView seqNumView;
@BindView(R.id.contributionProgress) ProgressBar progressView;
@BindView(R.id.failed_image_options) LinearLayout failedImageOptions;
private DisplayableContribution contribution;
ContributionViewHolder(View parent) {
imageView = parent.findViewById(R.id.contributionImage);
titleView = parent.findViewById(R.id.contributionTitle);
stateView = parent.findViewById(R.id.contributionState);
seqNumView = parent.findViewById(R.id.contributionSequenceNumber);
progressView = parent.findViewById(R.id.contributionProgress);
retryButton = parent.findViewById(R.id.retryButton);
cancelButton = parent.findViewById(R.id.cancelButton);
failedImageOptions=parent.findViewById(R.id.failed_image_options);
position = 0;
ButterKnife.bind(this, parent);
}
@Override
public void bindModel(Context context, DisplayableContribution contribution) {
this.contribution = contribution;
imageView.setMedia(contribution);
titleView.setText(contribution.getDisplayTitle());
seqNumView.setText(String.valueOf(contribution.getPosition() + 1));
seqNumView.setVisibility(View.VISIBLE);
switch (contribution.getState()) {
case Contribution.STATE_COMPLETED:
stateView.setVisibility(View.GONE);
progressView.setVisibility(View.GONE);
failedImageOptions.setVisibility(View.GONE);
stateView.setText("");
break;
case Contribution.STATE_QUEUED:
stateView.setVisibility(View.VISIBLE);
progressView.setVisibility(View.GONE);
stateView.setText(R.string.contribution_state_queued);
failedImageOptions.setVisibility(View.GONE);
break;
case Contribution.STATE_IN_PROGRESS:
stateView.setVisibility(View.GONE);
progressView.setVisibility(View.VISIBLE);
failedImageOptions.setVisibility(View.GONE);
long total = contribution.getDataLength();
long transferred = contribution.getTransferred();
if (transferred == 0 || transferred >= total) {
progressView.setIndeterminate(true);
} else {
progressView.setProgress((int)(((double)transferred / (double)total) * 100));
}
break;
case Contribution.STATE_FAILED:
stateView.setVisibility(View.VISIBLE);
stateView.setText(R.string.contribution_state_failed);
progressView.setVisibility(View.GONE);
failedImageOptions.setVisibility(View.VISIBLE);
break;
}
}
/**
* Retry upload when it is failed
*/
@OnClick(R.id.retryButton)
public void retryUpload() {
DisplayableContribution.ContributionActions actions = contribution.getContributionActions();
if (actions != null) {
actions.retryUpload();
}
}
/**
* Delete a failed upload attempt
*/
@OnClick(R.id.cancelButton)
public void deleteUpload() {
DisplayableContribution.ContributionActions actions = contribution.getContributionActions();
if (actions != null) {
actions.deleteUpload();
}
}
}

View file

@ -84,31 +84,25 @@ public class ContributionsFragment
ContributionsListFragment.SourceRefresher,
LocationUpdateListener,ICampaignsView
{
@Inject
@Named("default_preferences")
BasicKvStore defaultKvStore;
@Inject
ContributionDao contributionDao;
@Inject
MediaWikiApi mediaWikiApi;
@Inject
NotificationController notificationController;
@Inject
NearbyController nearbyController;
@Inject @Named("default_preferences") BasicKvStore defaultKvStore;
@Inject ContributionDao contributionDao;
@Inject MediaWikiApi mediaWikiApi;
@Inject NotificationController notificationController;
@Inject NearbyController nearbyController;
private ArrayList<DataSetObserver> observersWaitingForLoad = new ArrayList<>();
private Cursor allContributions;
private UploadService uploadService;
private boolean isUploadServiceConnected;
private CompositeDisposable compositeDisposable = new CompositeDisposable();
CountDownLatch waitForContributionsListFragment = new CountDownLatch(1);
private ContributionsListFragment contributionsListFragment;
private MediaDetailPagerFragment mediaDetailPagerFragment;
public static final String CONTRIBUTION_LIST_FRAGMENT_TAG = "ContributionListFragmentTag";
public static final String MEDIA_DETAIL_PAGER_FRAGMENT_TAG = "MediaDetailFragmentTag";
public NearbyNotificationCardView nearbyNotificationCardView;
@BindView(R.id.card_view_nearby) public NearbyNotificationCardView nearbyNotificationCardView;
@BindView(R.id.campaigns_view) CampaignView campaignView;
private Disposable placesDisposable;
private LatLng curLatLng;
@ -120,10 +114,7 @@ public class ContributionsFragment
private CheckBox checkBox;
private CampaignsPresenter presenter;
@BindView(R.id.campaigns_view) CampaignView campaignView;
/**
/**
* Since we will need to use parent activity on onAuthCookieAcquired, we have to wait
* fragment to be attached. Latch will be responsible for this sync.
*/
@ -159,7 +150,6 @@ public class ContributionsFragment
presenter = new CampaignsPresenter();
presenter.onAttachView(this);
campaignView.setVisibility(View.GONE);
nearbyNotificationCardView = view.findViewById(R.id.card_view_nearby);
checkBoxView = View.inflate(getActivity(), R.layout.nearby_permission_dialog, null);
checkBox = (CheckBox) checkBoxView.findViewById(R.id.never_ask_again);
checkBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
@ -359,7 +349,6 @@ public class ContributionsFragment
if (getActivity() != null) { // If fragment is attached to parent activity
getActivity().bindService(uploadServiceIntent, uploadServiceConnection, Context.BIND_AUTO_CREATE);
isUploadServiceConnected = true;
allContributions = contributionDao.loadAllContributions();
getActivity().getSupportLoaderManager().initLoader(0, null, ContributionsFragment.this);
}

View file

@ -3,12 +3,12 @@ package fr.free.nrw.commons.contributions;
import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.CursorAdapter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import fr.free.nrw.commons.R;
import fr.free.nrw.commons.contributions.model.DisplayableContribution;
import fr.free.nrw.commons.upload.UploadService;
import fr.free.nrw.commons.utils.NetworkUtils;
import fr.free.nrw.commons.utils.ViewUtil;
@ -20,13 +20,18 @@ class ContributionsListAdapter extends CursorAdapter {
private final ContributionDao contributionDao;
private UploadService uploadService;
private Context context;
public ContributionsListAdapter(Context context, Cursor c, int flags, ContributionDao contributionDao) {
public ContributionsListAdapter(Context context,
Cursor c,
int flags,
ContributionDao contributionDao) {
super(context, c, flags);
this.context = context;
this.contributionDao = contributionDao;
}
public void setUploadService( UploadService uploadService) {
public void setUploadService(UploadService uploadService) {
this.uploadService = uploadService;
}
@ -43,98 +48,55 @@ class ContributionsListAdapter extends CursorAdapter {
final ContributionViewHolder views = (ContributionViewHolder)view.getTag();
final Contribution contribution = contributionDao.fromCursor(cursor);
views.imageView.setMedia(contribution);
views.titleView.setText(contribution.getDisplayTitle());
views.seqNumView.setText(String.valueOf(cursor.getPosition() + 1));
views.seqNumView.setVisibility(View.VISIBLE);
views.position = cursor.getPosition();
switch (contribution.getState()) {
case Contribution.STATE_COMPLETED:
views.stateView.setVisibility(View.GONE);
views.progressView.setVisibility(View.GONE);
views.failedImageOptions.setVisibility(View.GONE);
views.stateView.setText("");
break;
case Contribution.STATE_QUEUED:
views.stateView.setVisibility(View.VISIBLE);
views.progressView.setVisibility(View.GONE);
views.stateView.setText(R.string.contribution_state_queued);
views.failedImageOptions.setVisibility(View.GONE);
break;
case Contribution.STATE_IN_PROGRESS:
views.stateView.setVisibility(View.GONE);
views.progressView.setVisibility(View.VISIBLE);
views.failedImageOptions.setVisibility(View.GONE);
long total = contribution.getDataLength();
long transferred = contribution.getTransferred();
if (transferred == 0 || transferred >= total) {
views.progressView.setIndeterminate(true);
} else {
views.progressView.setProgress((int)(((double)transferred / (double)total) * 100));
}
break;
case Contribution.STATE_FAILED:
views.stateView.setVisibility(View.VISIBLE);
views.stateView.setText(R.string.contribution_state_failed);
views.progressView.setVisibility(View.GONE);
views.failedImageOptions.setVisibility(View.VISIBLE);
views.retryButton.setOnClickListener(new View.OnClickListener() {
DisplayableContribution displayableContribution = new DisplayableContribution(contribution,
cursor.getPosition(),
new DisplayableContribution.ContributionActions() {
@Override
public void onClick(View view) {
retryUpload(cursor);
public void retryUpload() {
ContributionsListAdapter.this.retryUpload(contribution);
}
@Override
public void deleteUpload() {
ContributionsListAdapter.this.deleteUpload(contribution);
}
});
views.cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
deleteUpload(cursor);
}
});
break;
}
views.bindModel(context, displayableContribution);
}
/**
* Retry upload when it is failed
* @param cursor cursor will be retried
* @param contribution contribution to be retried
*/
public void retryUpload(Cursor cursor) {
if (NetworkUtils.isInternetConnectionEstablished(mContext)) {
Contribution c = contributionDao.fromCursor(cursor);
if (c.getState() == STATE_FAILED) {
uploadService.queue(UploadService.ACTION_UPLOAD_FILE, c);
Timber.d("Restarting for %s", c.toString());
private void retryUpload(Contribution contribution) {
if (NetworkUtils.isInternetConnectionEstablished(context)) {
if (contribution.getState() == STATE_FAILED
&& uploadService!= null) {
uploadService.queue(UploadService.ACTION_UPLOAD_FILE, contribution);
Timber.d("Restarting for %s", contribution.toString());
} else {
Timber.d("Skipping re-upload for non-failed %s", c.toString());
Timber.d("Skipping re-upload for non-failed %s", contribution.toString());
}
} else {
ViewUtil.showLongToast(mContext,R.string.this_function_needs_network_connection);
ViewUtil.showLongToast(context, R.string.this_function_needs_network_connection);
}
}
/**
* Delete a failed upload attempt
* @param cursor cursor which will be deleted
* @param contribution contribution to be deleted
*/
public void deleteUpload(Cursor cursor) {
if (NetworkUtils.isInternetConnectionEstablished(mContext)) {
Contribution c = contributionDao.fromCursor(cursor);
if (c.getState() == STATE_FAILED) {
Timber.d("Deleting failed contrib %s", c.toString());
contributionDao.delete(c);
private void deleteUpload(Contribution contribution) {
if (NetworkUtils.isInternetConnectionEstablished(context)) {
if (contribution.getState() == STATE_FAILED) {
Timber.d("Deleting failed contrib %s", contribution.toString());
contributionDao.delete(contribution);
} else {
Timber.d("Skipping deletion for non-failed contrib %s", c.toString());
Timber.d("Skipping deletion for non-failed contrib %s", contribution.toString());
}
} else {
ViewUtil.showLongToast(mContext,R.string.this_function_needs_network_connection);
ViewUtil.showLongToast(context, R.string.this_function_needs_network_connection);
}
}

View file

@ -1,7 +1,5 @@
package fr.free.nrw.commons.contributions;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
@ -121,13 +119,6 @@ public class ContributionsListFragment extends CommonsDaggerSupportFragment {
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
ContributionsFragment parentFragment = (ContributionsFragment)getParentFragment();
parentFragment.waitForContributionsListFragment.countDown();
}
/**
* Responsible to set progress bar invisible and visible
* @param isVisible True when contributions list should be hidden.

View file

@ -0,0 +1,54 @@
package fr.free.nrw.commons.contributions.model;
import fr.free.nrw.commons.contributions.Contribution;
public class DisplayableContribution extends Contribution {
private int position;
private ContributionActions contributionActions;
private DisplayableContribution(Contribution contribution,
int position) {
super(contribution.getContentUri(),
contribution.getFilename(),
contribution.getLocalUri(),
contribution.getImageUrl(),
contribution.getDateCreated(),
contribution.getState(),
contribution.getDataLength(),
contribution.getDateUploaded(),
contribution.getTransferred(),
contribution.getSource(),
contribution.getDescription(),
contribution.getCreator(),
contribution.getMultiple(),
contribution.getWidth(),
contribution.getHeight(),
contribution.getLicense());
this.position = position;
}
public DisplayableContribution(Contribution contribution,
int position,
ContributionActions contributionActions) {
this(contribution, position);
this.contributionActions = contributionActions;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public ContributionActions getContributionActions() {
return contributionActions;
}
public interface ContributionActions {
void retryUpload();
void deleteUpload();
}
}

View file

@ -0,0 +1,7 @@
package fr.free.nrw.commons.widget;
import android.content.Context;
public interface ViewHolder<T> {
void bindModel(Context context, T model);
}