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

Time:02-08

Some functions take a long time to execute. I want to make the user wait with a progress bar. Unfortunately, when I run this one, it runs but only at the end of my function and not when I would like. Let me explain, I launch my progress bar with the "sendloading()" method but during my tests this bar is only displayed after the processing of the other functions "copyAssets" or "createOnClicBtnInsert()". Can someone explain to me why?

Here is my code :

 @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();
            }


        }
    });
}

Here is my code for the progress bar :

    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);
    }

}

CodePudding user response:

Android is an event driven OS that runs on a single main thread. Drawing is an event. That means in order to draw the main thread needs to return to the event loop. Your code does not return to the event loop until after you do all your processing. Thus it won't draw until after the processing is done.

The way to solve this is to use either a Thread or a Kotlin coroutine to do the processing, and allow the main thread to return to the event loop. BTW, if you have long lasting processing you should not be doing it on the main thread anyway- it freezes your UI and makes your app appear non responsive, for the same reason. The main thread should do short quick calculations and respond to OS events only.

CodePudding user response:

You should use an AsyncTask to execute your task in a separated Thread and update the progressbar in the UI thread. Here below a short example of it:

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
            publishProgress(i);
        }
        return null;
    }

    @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, "ERROR", Toast.LENGTH_LONG).show();
            else {
                Toast.makeText(context, "OK", Toast.LENGTH_LONG).show();
            }
        }
    }
}

CodePudding user response:

This can happen if there is a recursion condition at runtime. If you want, just use progressbar.setVisibility=View.VISIBLE where you want to show it, by default it remains progressbar.setVisibility=View.INVISIBLE. Can you try it this way?

  •  Tags:  
  • Related