有些函数执行起来需要很长时间。我想用进度条让用户等待。不幸的是,当我运行这个时,它只在我的函数结束时运行,而不是在我想要的时候运行。让我解释一下,我用";sendloading(("方法,但在我的测试过程中,该条仅在处理完其他函数"之后显示;copyAssets";或";createOnClicBtnInsert((";。有人能解释一下为什么吗?
这是我的代码:
@Override
public void onViewCreated(@NonNull final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view.findViewById(R.id.btnInsertDataset2).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(!hasPermissions(getContext(),Permissions)){
lay_dataset2 = view.findViewById(R.id.lay_dataset2);
messagePerm();
}else {
sendLoading(); //MY PROGRESS BAR
btnInsert = view.findViewById(R.id.btnInsertDataset2);
/** if perm ok -> insert*/
copyAssets();
createOnClicBtnInsert();
view.findViewById(R.id.btnDeleteDataset2).setEnabled(true);
Toast.makeText(getContext(), "Insert Success", Toast.LENGTH_SHORT).show();
}
}
});
}
这是我的进度条代码:
public void sendLoading() {
int llPadding = 30;
LinearLayout ll = new LinearLayout(getContext());
ll.setOrientation(LinearLayout.HORIZONTAL);
ll.setPadding(llPadding, llPadding, llPadding, llPadding);
ll.setGravity(Gravity.CENTER);
LinearLayout.LayoutParams llParam = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
llParam.gravity = Gravity.CENTER;
ll.setLayoutParams(llParam);
ProgressBar progressBar = new ProgressBar(getContext());
progressBar.setIndeterminate(true);
progressBar.setPadding(0, 0, llPadding, 0);
progressBar.setLayoutParams(llParam);
llParam = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
llParam.gravity = Gravity.CENTER;
TextView tvText = new TextView(getContext());
tvText.setText("Loading ...");
tvText.setTextColor(Color.parseColor("#000000"));
tvText.setTextSize(20);
tvText.setLayoutParams(llParam);
ll.addView(progressBar);
ll.addView(tvText);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setCancelable(true);
builder.setView(ll);
AlertDialog dialog = builder.create();
dialog.show();
Window window = dialog.getWindow();
if (window != null) {
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
layoutParams.copyFrom(dialog.getWindow().getAttributes());
layoutParams.width = LinearLayout.LayoutParams.WRAP_CONTENT;
layoutParams.height = LinearLayout.LayoutParams.WRAP_CONTENT;
dialog.getWindow().setAttributes(layoutParams);
}
}
Android是一个在单个主线程上运行的事件驱动操作系统。绘图是一件大事。这意味着为了绘制主线程,需要返回到事件循环。在完成所有处理之后,代码才会返回到事件循环。因此,在处理完成之前,它不会绘制。
解决这个问题的方法是使用Thread或Kotlin协程来进行处理,并允许主线程返回到事件循环。顺便说一句,如果你有长时间的处理,你无论如何都不应该在主线程上进行处理——因为同样的原因,它会冻结你的UI,让你的应用程序看起来没有响应。主线程应该进行简短的快速计算,并且只响应操作系统事件。
您应该使用AsyncTask在单独的线程中执行任务,并更新UI线程中的进度条。下面是一个简短的例子:
private class VeryLongTask extends AsyncTask<String, Integer, String> {
private final Context context;
public VeryLongTask(Context context) {
this.context = context;
}
@Override
protected String doInBackground(String... sUrl) {
for (int i = 0; i < 255; i++) {
// do your long task;
// in this simple example is made by 255 iteraction
if (anErrorOccured()) return "ERROR";
publishProgress(i);
}
return "OK";
}
@Override
protected void onPreExecute() {
super.onPreExecute();
// Initialize your progressbar to zero
yourSetProgressMethod(0);
}
@Override
protected void onProgressUpdate(Integer... progress) {
super.onProgressUpdate(progress);
yourSetProgressMethod(progress[0]);
}
@Override
protected void onPostExecute(String result) {
if (getActivity() != null) {
if (result != null)
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
}
}
}