Как показать диалог динамического вращения с использованием отдельного класса задач Async

В моем приложении я читаю текстовые файлы с веб-сервера с помощью Async Tasking из отдельного класса, потому что он используется во многих действиях, поэтому я сделал выделенный класс. Я пытаюсь показать диалог динамического движения, но он дает мне ошибку, когда я помещаю код в класс Async Tasking.

вот моя треска для 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;
 }

}
</string,>

Код, как я обращаюсь к этому классу

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

Вот результаты 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

Еще одна вещь, которую я хочу спросить. Извините, что беспокою вас, ребята, снова. Вот что, один из моих действий зависит от результатов 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();

в приведенном выше коде появляется следующий Toast перед тем, как появится Toast в AsyncTAsk. Вопрос в том, как я могу приостановить мой основной поток, чтобы дождаться завершения AsyncTAsk. Большое спасибо :)

4 ответа

Помимо использования правильного Context вы не должны использовать AsyncTask#get(). Никогда. Он блокирует поток Ui до тех пор, пока результат не будет доступен, и вы не сможете отобразить диалог прогресса за это время, потому что вы уже ожидаете результата.

Если вы хотите использовать 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

}
</string,>

И внутри вашей 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");
}

Обратите внимание, что код внутри onResult выполняется после того, как поток программы уже покинул метод urdu(View view).

Альтернативно для реализации обратного вызова как анонимного внутреннего класса (new UtilssssCallback(){...}) вы также можете позволить Activity реализовать интерфейс и сделать его методом. Выполнение этого способа выглядит менее запутанным, но по существу тем же.

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

....


Я предлагаю вам прочитать это объяснение по поводу различных типов Context Android. Существуют некоторые примеры Context которые не позволяют вам выполнять определенные действия, которые делают другие экземпляры Context (т.е. Service - это Context, который не допускает инфляцию макета).

В вашем случае вы передаете Context Application в конструктор AsyncTask, а затем в Dialog. Вместо этого вы должны использовать Context Activity.

Поскольку вы вызываете AsyncTask из Activity и Activity extends from Context вы можете использовать ключевое слово this в экземпляре AsyncTask как сказал Cata.


Я бы предложил две вещи:

  1. Использовать WeakReference при передаче контекста в AsyncTask
  2. Вызовите метод в своей Activity чтобы начать и остановить диалог выполнения

Что-то вроде этого:

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);
 }
</color></activity></activity></void,>

В вашем MainActivity вы реализуете метод showProgressDialog(boolean show).

И как отметил Эммануил, вы, скорее всего, передадите контекст Activity.


Попробуй это:

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

Где "this" должно быть Activity и assumming, что параметр представляет mContext на стороне Utilssssclass :).

А также обратите внимание на ответ Эммануэля.

licensed under cc by-sa 3.0 with attribution.