【问题标题】:Show loading dialog while running background operation Android运行后台操作Android时显示加载对话框
【发布时间】:2013-01-21 10:04:59
【问题描述】:

我需要在 android 上进行一些涉及逐像素编辑的图像处理。这需要一点时间,而且屏幕只是冻结在那里,所以我想做一个加载对话框,让用户知道程序仍在运行。

这个 editPhoto 函数是我需要在后台运行的。

 private void editPhoto() {
    if (editPhotoImg.getDrawable() == null) {
        Toast.makeText(getApplicationContext(), "No Photo Selected",
                Toast.LENGTH_SHORT).show();
    } else if (hasSample == false) {
        Toast.makeText(getApplicationContext(), "No Sample Photo Selected",
                Toast.LENGTH_SHORT).show();
    } else {


        detectFaces(false);


        BitmapDrawable ebm = (BitmapDrawable) editPhotoImg.getDrawable();

        Bitmap editTemp = ebm.getBitmap();
        PointF editFaceMidPoint = getFaceMidPoint(editTemp);

        BitmapDrawable sbm = (BitmapDrawable) samplePhotoImg.getDrawable();
        Bitmap sampleTemp = sbm.getBitmap();
        PointF sampleFaceMidPoint = getFaceMidPoint(sampleTemp);

        if (editFaceMidPoint != null && sampleFaceMidPoint != null) {
            int editFaceMidPointPixel = editTemp.getPixel(
                    (int) editFaceMidPoint.x, (int) editFaceMidPoint.y);
            int sampleFaceMidPointPixel = sampleTemp.getPixel(
                    (int) sampleFaceMidPoint.x, (int) sampleFaceMidPoint.y);

            editPhotoImg.setImageBitmap(shiftRGB(editTemp,
                    editFaceMidPointPixel, sampleFaceMidPointPixel));

            savePhoto();

            detectFaces(true);
        }
    }

}

这是我的 AsyncTask 代码,它没有达到我想要的效果。它给了我一个我什至无法识别的错误。谁能告诉我应该怎么做,或者我应该在哪里调用 editPhoto() 方法,以便它在加载对话框后面而不是在加载对话框之前或之后运行?

     private class LoadEditPhoto extends AsyncTask<Void, Integer, Void> {
    // Before running code in separate thread

    @Override
    protected void onPreExecute() {
        /* Create a new progress dialog
        progressDialog = new ProgressDialog(EditPhoto.this);
        // Set the progress dialog to display a horizontal progress bar
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        // Set the dialog title to 'Loading...'
        progressDialog.setTitle("Loading...");
        // Set the dialog message to 'Loading application View, please
        // wait...'
        progressDialog.setMessage("Loading application View, please wait...");
        */
        progressDialog = ProgressDialog.show(EditPhoto.this,"Loading...",  
                "Editing Photo, please wait...", false, false);  
        // This dialog can't be canceled by pressing the back key
        progressDialog.setCancelable(false);
        // This dialog isn't indeterminate
        progressDialog.setIndeterminate(false);
        // The maximum number of items is 100
        progressDialog.setMax(100);
        // Set the current progress to zero
        progressDialog.setProgress(0);
        // Display the progress dialog
        progressDialog.show();
    }

    // The code to be executed in a background thread.
    @Override
    protected Void doInBackground(Void... params) {
        /*
         * This is just a code that delays the thread execution 4 times,
         * during 850 milliseconds and updates the current progress. This is
         * where the code that is going to be executed on a background
         * thread must be placed.
         * 
         */


        editPhoto();
        publishProgress(100);
        return null;
    }

    // Update the progress
    @Override
    protected void onProgressUpdate(Integer... values) {
        // set the current progress of the progress dialog
        progressDialog.setProgress(values[0]);
    }

    // after executing the code in the thread
    @Override
    protected void onPostExecute(Void result) {
        // close the progress dialog
        progressDialog.dismiss();

    }
}

【问题讨论】:

    标签: android background android-asynctask loading


    【解决方案1】:

    删除 toast 消息,它应该可以工作。您无法从 doInBackground 方法更新 UI。除此之外,您的代码看起来不错。所以这应该是错误,。

    或使用 runOnUi() 来显示您的 Toast 消息。

    像这样围绕你的吐司,

    ActivityObject.runOnUiThread(new Runnable() {
    
            @Override
            public void run() {
                Toast.makeText(this, message, Toast.LENGTH_LONG).show();
            }
        });
    

    【讨论】:

    • 安德罗,谢谢你的建议。但不知何故,这仍然不适合我。它因 windowleaked 错误而崩溃 hmm
    • 它是因为您使用了应用程序上下文。而是将 Activity 的上下文用于 toast。像这样的东西,Toast.makeText(ActivityName.this, message, Toast.LENGTH_LONG).show();
    【解决方案2】:

    将您的editPhoto() 放入 线程

    现在定义以下代码来处理多条消息。

    public enum WhatAbout {
        START,STOP
    }
    
    public WhatAbout[] wa = WhatAbout.values();
    

    然后使用Handler,它可以帮助您沟通BackgroundThreadUIThread。 如果不使用处理程序,您将无法更改UI

    将以下代码放入您的 onCreate 方法中。

    handler = new Handler() {
      @Override
      public void handleMessage(Message msg) {
        if (msg.what < wa.length) {
        switch (wa[msg.what]) 
        {
        case START:
             progressDialog = ProgressDialog.show(getActivity(), null,
                            "Editing Photo... Please Wait...");
             break;
    
        case STOP:
             if (progressDialog.isShowing())
                progressDialog.dismiss();
    
             imageView.setImageBitmap(editedBitmap);
             break;
        }
      }
    };
    

    然后,当您在Thread 中开始 编辑 时,将以下代码放在editPhoto() 的第一行。

    handler.sendMessage(handler.obtainMessage(
                    WhatAbout.START.ordinal(), 0, 0));
    

    当您的editing 完成后,将以下代码放在editPhoto() 的末尾。

    handler.sendMessage(handler.obtainMessage(
                    WhatAbout.STOP.ordinal(), 0, 0));
    

    【讨论】:

    • Chintan,感谢您的友好解释!但是作为android编程的新手,尽管你描述了如何一步一步,我仍然无法实现它。我再次在下面发布了我的代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-25
    相关资源
    最近更新 更多