简体   繁体   English

如何使用单独的异步任务类显示旋转进度对话框

[英]How to show spinning progress dialogue with using separate Async Task Class

In my app, i'm reading text files from web server using Async Tasking from a separate class because it is used in many activities, so i've made a dedicated class. 在我的应用程序中,我正在使用Async Tasking从一个单独的类中从Web服务器读取文本文件,因为它在许多活动中都使用过,所以我做了一个专门的类。 I'm trying to show a spinning progress dialogue but it is giving me error when i put the code in Async Tasking class. 我正在尝试显示旋转进度对话框,但是当我将代码放入Async Tasking类时却给了我错误。

here is my cod for Async Task Class 这是我异步任务班的鳕鱼

public class Utilssss extends AsyncTask<String, String, String> {
    private Context         mContext;
    private ProgressDialog  pdia;

    // constructor
    public Utilssss(Context activityContext) {
        mContext = activityContext;
    }

    protected void onPreExecute() {
        super.onPreExecute();
        pdia = new ProgressDialog(mContext);
        pdia.setMessage("Loading...");
        pdia.show();
    }

    protected String doInBackground(String... url) {
        return GetLinkss(url[0]);

    }

    protected void onPostExecute(String result) {
        // Toast.makeText(mContext, result, Toast.LENGTH_LONG).show();
        super.onPostExecute(result);
        pdia.dismiss();
    }

    private String GetLinkss(String url) {

        // your stuff
        String StringBuffer = "";
        String stringText = "";
        try {
            URL link = new URL(url);
            BufferedReader bufferReader = new BufferedReader(new InputStreamReader(link.openStream()));

            while ((StringBuffer = bufferReader.readLine()) != null) {
                stringText += StringBuffer;
            }
            bufferReader.close();
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return stringText;
    }

}

Code how i'm accessing this class 编码我如何上这堂课

public void urdu(View view) throws InterruptedException, ExecutionException {
        String fileexist = null;

        fileexist = new Utilssss(getBaseContext()).execute("http://192.168.1.2/eWorldLiterature/urdu/index.txt").get();

        Toast.makeText(getBaseContext(), fileexist, Toast.LENGTH_SHORT).show();

        // if (fileexist != 229) {
        Intent i = new Intent(getBaseContext(), MainPage.class);
        i.putExtra(LANGUAGE, "urdu");
        startActivity(i);

Here is the LogCat results. 这是LogCat结果。

12-05 00:38:06.266: E/AndroidRuntime(28766): FATAL EXCEPTION: main
12-05 00:38:06.266: E/AndroidRuntime(28766): java.lang.IllegalStateException: Could not execute method of the activity
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.View$1.onClick(View.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.View.performClick(View.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.View$PerformClick.run(View.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.os.Handler.handleCallback(Handler.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.os.Handler.dispatchMessage(Handler.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.os.Looper.loop(Looper.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.app.ActivityThread.main(ActivityThread.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at java.lang.reflect.Method.invokeNative(Native Method)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at java.lang.reflect.Method.invoke(Method.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at dalvik.system.NativeStart.main(Native Method)
12-05 00:38:06.266: E/AndroidRuntime(28766): Caused by: java.lang.reflect.InvocationTargetException
12-05 00:38:06.266: E/AndroidRuntime(28766):    at java.lang.reflect.Method.invokeNative(Native Method)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at java.lang.reflect.Method.invoke(Method.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    ... 12 more
12-05 00:38:06.266: E/AndroidRuntime(28766): Caused by: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.ViewRootImpl.setView(ViewRootImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.WindowManagerImpl.addView(WindowManagerImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.app.Dialog.show(Dialog.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at md.literature.imranseries.Utilssss.onPreExecute(Utilssss.java:35)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.os.AsyncTask.executeOnExecutor(AsyncTask.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at android.os.AsyncTask.execute(AsyncTask.java)
12-05 00:38:06.266: E/AndroidRuntime(28766):    at md.literature.imranseries.Selection.urdu(Selection.java:65)
12-05 00:38:06.266: E/AndroidRuntime(28766):    ... 14 more

Just one more thing i want to ask. 我还想问一件事。 Sorry to bother you guys again.. Here is the thing, one of my activity relies on the results of Asynctask and should no proceed unless the task is completed, but this is not happening, here is a sample piece of code which proves it. 抱歉,再次打扰您。.事情在这里,我的活动之一依赖于Asynctask的结果,除非任务完成,否则不应该继续进行,但是这种情况没有发生,这里有一段代码证明了这一点。

        final Context context = this;
        new Utils(context, new Utils.UtilsCallback() {
            @Override
            public void onResult(String lstr) {
//              lstr = string;
                Toast.makeText(getBaseContext(), "Now Raeading" + Novelselected, Toast.LENGTH_LONG).show();
            }
        }).execute(ulti_link + "/" + Novelselected.replace(" ", "%20") + ".txt");

        Toast.makeText(getBaseContext(), "Now Raeading", Toast.LENGTH_LONG).show();

in the above code, the following Toast appears before the Toast within the AsyncTAsk appears, The question is, how can i pause my main thread to wait for the AsyncTAsk to complete. 在上面的代码中,在AsyncTAsk中的Toast出现之前,以下Toast出现了,问题是,我如何暂停我的主线程以等待AsyncTAsk完成。 Thanks a lot :) 非常感谢 :)

I suggest you read this explanation about the different types of Context Android has. 我建议你阅读有关不同类型的解释Context Android了。 There are some instances of Context that do not allow you to do certain things that other Context instances do (ie Service is a Context that doesn't allow layout inflation). 有些Context实例不允许您做某些其他Context实例可以做的事情(即Service是不允许布局膨胀的Context )。

In your case you are passing the Application Context to the AsyncTask constructor, and subsequently to the Dialog . 在您的情况下,您要将Application Context传递给AsyncTask构造函数,然后传递给Dialog You should use an Activity Context instead. 您应该改为使用Activity Context

Since you are calling the AsyncTask from an Activity and Activity extends from Context you can use the keyword this in the AsyncTask instantiation like Cata said. 由于您是从Activity调用AsyncTask ,而ActivityContext扩展的,因此您可以在AsyncTask实例化中使用关键字this ,如Cata所说。

Besides using the correct Context you must not use AsyncTask#get() . 除了使用正确的Context您不得使用AsyncTask#get() Never. 决不。 It blocks the Ui thread until the result is available and you can not show a progress dialog during that time then because you are already waiting for the result. 它会阻塞Ui线程,直到结果可用,并且在那期间您无法显示进度对话框,因为您已经在等待结果。

If you want to use an AsyncTask from a different class add a callback mechanism of your own. 如果要使用其他类中的AsyncTask,请添加自己的回调机制。

public class Utilssss extends AsyncTask<String, String, String> {

    /** Implement this somewhere to get the result */
    public interface UtilssssCallback {
        void onResult(String string);
    }

    private Context mContext;
    private ProgressDialog pdia;

    private UtilssssCallback mListener;

    // constructor
    public Utilssss(Context activityContext, UtilssssCallback listener) {
        mContext = activityContext;
        mListener = listener; // save callback
    }

    @Override
    protected void onPostExecute(String result) {
        pdia.dismiss();
        mListener.onResult(result);
    }

    // rest omitted since unchanged

}

And inside your Activity 在你的Activity

public void urdu(View view) {
    final Context context = this;
    new Utilssss(context, new Utilssss.UtilssssCallback() {
        @Override
        public void onResult(String string) {
            Toast.makeText(context, string, Toast.LENGTH_LONG).show();
            Intent i = new Intent(context, MainPage.class);
            i.putExtra(LANGUAGE, "urdu");
            context.startActivity(i);
        }
    }).execute("http://192.168.1.2/eWorldLiterature/urdu/index.txt");
}

Note that the code inside onResult is executed way after the program flow has already left the urdu(View view) method. 请注意, onResult内部的代码是在程序流已经离开urdu(View view)方法之后执行的。


Alternatively to implementing the callback as an anonymous inner class ( new UtilssssCallback(){...} ) you could also let the Activity implement the interface and make it a method. 除了将回调实现为匿名内部类( new UtilssssCallback(){...} )之外,您还可以让Activity实现接口并将其作为方法。 Doing it that way looks less confusing but is essentially the same. 以这种方式进行操作看起来不太混乱,但本质上是相同的。

public class TheActivity extends FragmentActivity implements UtilssssCallback {

    public void urdu(View view) {
        // those two are not necessary but help make it obvious what parameters we have
        Context context = this;
        UtilssssCallback callback = this; // the class implements that
        new Utilssss(context, callback).execute("http://192.168.1.2/eWorldLiterature/urdu/index.txt");
    }

    @Override
    public void onResult(String string) {
        Toast.makeText(context, string, Toast.LENGTH_LONG).show();
    }

....

I would suggest two things: 我建议两件事:

  1. Use a WeakReference when passing a context to an AsyncTask 将上下文传递到AsyncTask时使用WeakReference
  2. Call a method on your Activity to start and stop your progress dialog 在“ Activity上调用方法以启动和停止进度对话框

Something like this: 像这样:

public class ProgressAsyncTask extends AsyncTask<Void, Void, Void> {

    private WeakReference<Activity> weakActivity;

    public ProgressAsyncTask(Activity activity) {
        weakActivity = new WeakReference<Activity>(activity);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        Activity activity = weakActivity.get();
        ((MainActivity) activity).showProgressDialog(true);

    }

    @Override
    protected void doInBackground(Void... params) {
        // Do stuff
    }

    @Override
    protected void onPostExecute(List<Color> result) {
        super.onPostExecute(result);

        Activity activity = weakActivity.get();
        ((MainActivity) activity).showProgressDialog(false);
    }

In your MainActivity you implement the method showProgressDialog(boolean show) . 在您的MainActivity中,实现方法showProgressDialog(boolean show)

And as Emmanuel pointed out you should most likely pass an Activity 's context. 正如伊曼纽尔(Emmanuel)指出的那样,您最有可能应该传递Activity的上下文。

Try this: 尝试这个:

fileexist = new Utilssss(this).execute("http://192.168.1.2/eWorldLiterature/urdu/index.txt").get();

Where "this" should be the Activity and assumming that the parameter represents the mContext on the Utilssssclass side :). 其中“ this”应为Activity,并假定参数代表Utilssssclass端的mContext :)。

And also pay attention to Emmanuel's answer too. 并且也要注意伊曼纽尔的回答。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM