尝试在列表视图中显示每个文件上传的进度时 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 卡住的主要内容,如果未能解决你的问题,请参考以下文章
当我在 Android 中将文件上传到 Firebase 存储时,进度条没有更新