如何在我的函数执行期间显示加载消息?

How to display loading message during the execution of my function?

有些功能需要很长时间才能执行。我想让用户等待进度条。 不幸的是,当我 运行 这个时,它 运行s 但只是在我的函数结束时而不是我想要的时候。 让我解释一下,我使用“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 是在单个主线程上运行的事件驱动 OS。绘画是一个事件。这意味着为了绘制主线程需要 return 到事件循环。在您完成所有处理之前,您的代码不会 return 进入事件循环。因此在处理完成后才会绘制。

解决这个问题的方法是使用线程或Kotlin协程来处理,并让主线程return进入事件循环。顺便说一句,如果你有持久的处理,你不应该在主线程上做它无论如何 - 它会冻结你的 UI 并使你的应用程序看起来没有响应,出于同样的原因。主线程应该进行简短的快速计算并仅响应 OS 个事件。

您应该使用 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();
            }
        }
    }
}