【问题标题】:UI stuck while trying to show progress of each file upload in listview尝试在列表视图中显示每个文件上传的进度时 UI 卡住
【发布时间】:2018-04-06 22:07:51
【问题描述】:

我试图在 ListView 中将多个文件上传到 Box.com 时显示它们的进度。我正在使用从这个链接https://github.com/lzyzsd/CircleProgress 找到的甜甜圈进度条来显示列表中每个项目的进度。

但是,我在上传时似乎无法更新 UI。 UI 卡住了,甚至没有响应用户的点击。每个项目的进度条从 0% 开始,只有在每次上传完成后才会变为 100%。由于 UI 卡住,中间的所有百分比均未显示。

我目前正在为列表视图中的每个项目使用自定义视图。我这样做是因为我希望每个视图都实现一个进度监听器。然后我将每个视图添加到各自的异步任务中,并从那里更新进度。

以下是我的代码:

我用于 ListView 的适配器

public class SurveyListAdapter extends BaseAdapter {

private LayoutInflater inflater;
private LinkedList<File> files;
private static LinkedList<String> savedIDs;
private ViewHolder holder;
private BoxApiFile mFileApi;
private HomeActivity homeActivity;
private int [] progress;
private int mScrollState = AbsListView.OnScrollListener.SCROLL_STATE_IDLE;
private ListView listView;
private File file;

public class ViewHolder {
    TextView fileIDTextView;
    TextView dateModifiedTextView;
    DonutProgress fileUploadProgress;
    CustomSurveyView customSurveyView;
    UploadToBoxTask uploadTask;
}

public SurveyListAdapter(HomeActivity homeActivity, LinkedList<File> files, ListView listView) {
    this.homeActivity = homeActivity;
    inflater = LayoutInflater.from(homeActivity);
    this.files = files;
    savedIDs = new LinkedList<>();
    progress = new int [files.size()];
    this.listView = listView;
}

public int getCount() {
    return files.size();
}

public File getItem(int position) {
    return files.get(position);
}

public long getItemId(int position) {
    return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
    file = files.get(position);
    holder = null;
    if(convertView == null) {
        holder = new ViewHolder();
        convertView = inflater.inflate(R.layout.survey_list_view, null);
        holder.customSurveyView = (CustomSurveyView) convertView.findViewById(R.id.customSurveyView);
        holder.fileUploadProgress = holder.customSurveyView.getDonutProgress();
        holder.fileIDTextView = holder.customSurveyView.getFileIDTextView();
        holder.dateModifiedTextView = holder.customSurveyView.getDateModifiedTextView();
        holder.uploadTask = new UploadToBoxTask(this, holder.customSurveyView, file);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }
    String fileName = file.getName();
    String fileShouldStartWith = HomeActivity.FILE_SHOULD_START_WITH;
    String fileShouldEndWith = HomeActivity.FILE_SHOULD_END_WITH;

    String ID = fileName.substring(fileShouldStartWith.length(), fileName.length() - fileShouldEndWith.length()).trim();
    savedIDs.add(ID);

    SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy   hh:mm a");
    String lastDateModified = sdf.format(file.lastModified());

    holder.fileIDTextView.setText("Subject ID " + ID);
    holder.dateModifiedTextView.setText(lastDateModified);

    return convertView;
}

public View getViewByPosition(int pos) {
    final int firstListItemPosition = listView.getFirstVisiblePosition();
    final int lastListItemPosition = firstListItemPosition + listView.getChildCount() - 1;

    if (pos < firstListItemPosition || pos > lastListItemPosition ) {
        return listView.getAdapter().getView(pos, null, listView);
    } else {
        final int childIndex = pos - firstListItemPosition;
        return listView.getChildAt(childIndex);
    }
}

public static LinkedList<String> getSavedIDs() {
    return savedIDs;
}

public void syncWithBox(BoxApiFile mFileApi){
    this.mFileApi = mFileApi;

    ExecutorService executor = Executors.newSingleThreadExecutor();
    for (int i = 0; i < files.size(); i++) {
        ViewHolder holder = (ViewHolder) getViewByPosition(i).getTag();
        holder.fileUploadProgress.setVisibility(View.VISIBLE);
        holder.uploadTask.executeOnExecutor(executor);}

    executor.shutdown();

    while (!executor.isTerminated()) { }

    System.out.println("Finished uploading");
}

private class UploadToBoxTask extends AsyncTask<Void, Integer, Void>{

    SurveyListAdapter surveyListAdapter;
    BoxUploadProgressListener progressListener;
    File uploadFile;

    public UploadToBoxTask(SurveyListAdapter surveyListAdapter, BoxUploadProgressListener progressListener, File uploadFile){
        this.surveyListAdapter = surveyListAdapter;
        this.progressListener = progressListener;
        this.uploadFile = uploadFile;
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {
            final BoxRequestsFile.UploadFile request = mFileApi.getUploadRequest(uploadFile, BoxConstants.ROOT_FOLDER_ID);
            request.setProgressListener(new ProgressListener() {
                @Override
                public void onProgressChanged(long numBytes, long totalBytes) {
                    publishProgress((int) (100 * (numBytes/totalBytes)));
                }
            });
            final BoxFile uploadFileInfo = request.send();
            showToast("Uploaded " + uploadFileInfo.getName());
            //loadRootFolder();
        } catch (BoxException e) {
            BoxError error = e.getAsBoxError();
            if (error != null && error.getStatus() == HttpURLConnection.HTTP_CONFLICT) {
                ArrayList<BoxEntity> conflicts = error.getContextInfo().getConflicts();
                if (conflicts != null && conflicts.size() == 1 && conflicts.get(0) instanceof BoxFile) {
                    //uploadNewVersion((BoxFile) conflicts.get(0), position, adapter);
                    publishProgress(100);
                    return null;
                }
            }
            showToast("Upload failed");
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... integers){
        progressListener.onProgressUpdate(integers[0]);
        showToast(String.valueOf(integers[0]));
    }

    @Override
    protected void onPostExecute(Void param){

    }
}
}

我创建的自定义视图:

public class CustomSurveyView extends RelativeLayout  implements BoxUploadProgressListener{
View rootView;
LinearLayout linearLayout;
TextView fileIDTextView;
TextView dateModifiedTextView;
DonutProgress donutProgress;

public CustomSurveyView(Context context) {
    super(context);
    init(context);
}

public CustomSurveyView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

private void init(Context context) {
    rootView = inflate(context, R.layout.custom_survey_view, this);
    linearLayout = rootView.findViewById(R.id.fileInfoLayout);
    fileIDTextView = rootView.findViewById(R.id.fileIDTextView);
    dateModifiedTextView = rootView.findViewById(R.id.dateModifiedTextView);
    donutProgress = rootView.findViewById(R.id.fileUploadProgressBar);
}

@Override
public void onProgressUpdate(int progress) {
    donutProgress.setVisibility(View.VISIBLE);
    ObjectAnimator anim = ObjectAnimator.ofInt(donutProgress, "progress", donutProgress.getProgress(), progress);
    donutProgress.setProgress(progress);
    anim.setInterpolator(new DecelerateInterpolator());
    anim.setDuration(500);
    anim.start();
    invalidate();
}

public LinearLayout getLinearLayout() {
    return linearLayout;
}

public TextView getFileIDTextView() {
    return fileIDTextView;
}

public TextView getDateModifiedTextView() {
    return dateModifiedTextView;
}

public DonutProgress getDonutProgress() {
    return donutProgress;
}
}

我创建的进度监听接口

public interface BoxUploadProgressListener {
    void onProgressUpdate(int progress);
}

这就是我的布局的样子

请帮助正确更新每次上传进度的 UI。我已经在这两天了。

【问题讨论】:

    标签: android multithreading listview android-asynctask box-api


    【解决方案1】:

    可能的原因:

    1. 避免从异步任务更改 Ui

    2. 避免与每个持有者实例一起添加新线程,这会增加 RAM 消耗,因为应用程序没有响应。

    在主线程中创建界面并更新 UI。

    【讨论】:

    • 那不是问题。不过感谢您的帮助。
    【解决方案2】:

    我发现了问题。它是我在执行程序之后放置的while循环。它一直运行直到所有任务完成。

    【讨论】:

      猜你喜欢
      • 2020-12-08
      • 2014-02-25
      • 2016-10-25
      • 2017-11-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-19
      • 2023-01-22
      相关资源
      最近更新 更多