尝试在列表视图中显示每个文件上传的进度时 UI 卡住

Posted

技术标签:

【中文标题】尝试在列表视图中显示每个文件上传的进度时 UI 卡住【英文标题】:UI stuck while trying to show progress of each file upload in listview 【发布时间】: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。我已经在这两天了。

【问题讨论】:

【参考方案1】:

可能的原因:

    避免从异步任务更改 Ui

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

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

【讨论】:

那不是问题。不过感谢您的帮助。【参考方案2】:

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

【讨论】:

以上是关于尝试在列表视图中显示每个文件上传的进度时 UI 卡住的主要内容,如果未能解决你的问题,请参考以下文章

多个图像上传进度问题

遍历选项卡列表并使用 if 语句显示不同的视图

Ant设计文件上传中使用customRequest

当我在 Android 中将文件上传到 Firebase 存储时,进度条没有更新

文件上传进度的通知观察者模式仅在文件很大时才有效 - swift?

Swift UI:当视图中显示空列表时,如何显示错误消息?