AsyncTask onPreExecute progressdialog

时间:2011-04-29 13:30:06

标签: android android-asynctask

当onPreExecute函数执行时,我有一个AsyncTask,它给我一个异常

  

** java.lang.IllegalStateException:View   com.android.internal.policy.impl.PhoneWindow$DecorView@44ea0e20   已添加到窗口中   管理器。**

调用progressDialog的show()方法时。

我的活动

public class TopNewsActivity extends ListActivity {

public static final String LOG_TAG = "Infra";
private ProgressDialog progressDialog;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.listplaceholder);
    new BackgroundAsyncTask().execute();
}

public class BackgroundAsyncTask extends AsyncTask<String, Integer, ArrayList<HashMap<String, String>>> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progressDialog = new ProgressDialog(TopNewsActivity.this);
        progressDialog.setCancelable(true);
        progressDialog.setMessage("Loading...");
        progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        progressDialog.setProgress(0);
        progressDialog.show();
    }

    @Override
    protected ArrayList<HashMap<String, String>> doInBackground(String... paths) {
        ArrayList<HashMap<String, String>> mylist = new ArrayList<HashMap<String, String>>();

        String xml = XMLfunctions.getTopNewsXML();
        Document doc = XMLfunctions.XMLfromString(xml);

        int numResults = XMLfunctions.numResults(doc);
        Log.d(LOG_TAG, "Number of Results: " + numResults);
        if ((numResults <= 0)) {
            Toast.makeText(TopNewsActivity.this, "No Result Found",Toast.LENGTH_LONG).show();
            finish();
        }

        NodeList nodes = doc.getElementsByTagName("result");

        for (int i = 0; i < nodes.getLength(); i++) {
            HashMap<String, String> map = new HashMap<String, String>();

            Element e = (Element) nodes.item(i);
            map.put("id", XMLfunctions.getValue(e, "id"));
            map.put("title", XMLfunctions.getValue(e, "title"));
            mylist.add(map);
        }
        return mylist;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
    }

    protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
        ListAdapter adapter = new SimpleAdapter(TopNewsActivity.this, result, R.layout.list_item, new String[] { "title" }, new int[] { R.id.item_title });
        setListAdapter(adapter);
        progressDialog.dismiss();

        final ListView lv = getListView();

        lv.setTextFilterEnabled(true);  
        lv.setOnItemClickListener(new OnItemClickListener() {
            @SuppressWarnings("unchecked")
            @Override
            public void onItemClick(AdapterView<?> a, View view, final int position, long id) {

                    HashMap<String, String> o = (HashMap<String, String>) lv.getItemAtPosition(position);

                    Intent i = new Intent(TopNewsActivity.this, NewsDetails.class);
                    i.putExtra("content_id", o.get("id"));
                    i.putExtra("title", o.get("title"));
                    i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

                    View v = TopNewsGroup.group.getLocalActivityManager().startActivity("ShowNews", i).getDecorView();

                    // Again, replace the view
                    TopNewsGroup.group.setContentView(v);

            }
        });

    }

}

public class MySimpleAdapter extends SimpleAdapter {
     public MySimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to) {
        super(context, data, resource, from, to);
        // TODO Auto-generated constructor stub
}

}
}

请帮助!!!!!

7 个答案:

答案 0 :(得分:4)

progressdialogs和contexts有一个常见的问题,它总是发生在我身上,并且在这个问题上有一个关于android doc的部分。当上下文实际上是您的Java类的名称后跟“.this”时,您可能已使用“this”上下文声明它。

dialog = ProgressDialog.show(Example.this, "",
                "Doing stuff. Please wait...", true);

这是因为您希望progressDialog在主类中显示,而不是在Async类中显示。

如果这不能解决问题,您需要发布代码。

答案 1 :(得分:2)

if ((numResults <= 0)) {
    Toast.makeText(TopNewsActivity.this, "No Result Found.",Toast.LENGTH_LONG).show();
    finish();
}

我认为这不是一件好事。不要从非ui线程完成您的活动。只需返回null。

答案 2 :(得分:1)

尝试删除super.onPreExecute();

答案 3 :(得分:1)

谢谢大家,但我已经弄明白问题是什么,我正在使用ActivityGroup所以我需要把 progressDialog = new ProgressDialog(TopNewsGroup.group); 这解决了我的问题

:)

答案 4 :(得分:0)

尝试使用此代码

import java.util.ArrayList;
import java.util.HashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.Toast;

import com.example.tabs.R;
import com.s3.daycare.adapters.CalendarAdapter;
import com.s3.daycare.description.CalendarDescription;

public class Calendar extends Activity {

    String url = "http://mobile.s3technology.net/DayCare/webservices/Get_calender.php?";

    GetData data;

    ProgressDialog progressDialog;

    ListView list_of_calendar;

    ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.calendar);

        list_of_calendar = (ListView) findViewById(R.id.list_of_calendar);

        new GetData().execute();

        //ListView listView = getListView();
        list_of_calendar.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) 
            {
                HashMap<String, String> map = list.get(position);               

                Intent intent = new Intent(Calendar.this, CalendarDescription.class);

                intent.putExtra("name", map.get("name"));

                intent.putExtra("date", map.get("date"));

                intent.putExtra("description", map.get("description"));

                startActivity(intent);


            }

        });
    }

    private class GetData extends AsyncTask<String, Void, JSONObject> {

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

            progressDialog = ProgressDialog.show(Calendar.this,
                    "", "");

        }

        @Override
        protected JSONObject doInBackground(String... params) {

            String response;

            try {

                HttpClient httpclient = new DefaultHttpClient();

                HttpPost httppost = new HttpPost(url);

                HttpResponse responce = httpclient.execute(httppost);

                HttpEntity httpEntity = responce.getEntity();

                response = EntityUtils.toString(httpEntity);

                Log.d("response is", response);

                return new JSONObject(response);

            } catch (Exception ex) {

                ex.printStackTrace();

            }

            return null;
        }

        @Override
        protected void onPostExecute(JSONObject result) 
        {
            super.onPostExecute(result);

            progressDialog.dismiss();

            if(result != null)
            {
                try
                {
                    JSONObject jobj = result.getJSONObject("result");

                    String status = jobj.getString("status");

                    if(status.equals("true"))
                    {
                        JSONArray array = jobj.getJSONArray("data");

                        for(int x = 0; x < array.length(); x++)
                        {
                            HashMap<String, String> map = new HashMap<String, String>();

                            map.put("name", array.getJSONObject(x).getString("name"));

                            map.put("date", array.getJSONObject(x).getString("date"));

                            map.put("description", array.getJSONObject(x).getString("description"));

                            list.add(map);
                        }

                        CalendarAdapter adapter = new CalendarAdapter(Calendar.this, list);

                        list_of_calendar.setAdapter(adapter);
                    }
                }
                catch (Exception e) 
                {
                    e.printStackTrace();
                }
            }
            else
            {
                Toast.makeText(Calendar.this, "Network Problem", Toast.LENGTH_LONG).show();
            }
        }

    }
}

答案 5 :(得分:0)

您可以使用setProgressBaIndeterminateVisibility(true)

@Override
    protected void onPreExecute() {
        setProgressBarIndeterminateVisibility(true);
    }

答案 6 :(得分:0)

Dialog为例。

从Android源代码来看,让我们看看调用方法Dialog#show()方法时发生了什么。该代码可以简化如下:

    public void show() {
        if (mShowing) {
            // ...
            return;
        }
        // ...
        mDecor = mWindow.getDecorView();
        mWindowManager.addView(mDecor, l);
        // ...
        mShowing = true;
        // ...
    }

mDecor字段来自mWidnowmWindow字段来自Dialog的构造:

    Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
        // ...
        final Window w = new PhoneWindow(mContext);
        mWindow = w;
        // ...
    }

所以这意味着一个Dialog有一个mWindow,一个mWindow有一个mDecor

调用mWindowManager.addView(mDecor, l)时,它转到了WindowManagerGlobal#addView()

    public void addView(View view, ViewGroup.LayoutParams params,
            Display display, Window parentWindow) {
        // ...
        synchronized (mLock) {
            // ...
            int index = findViewLocked(view, false);
            if (index >= 0) {
                if (mDyingViews.contains(view)) {
                    mRoots.get(index).doDie();
                } else {
                    // EXCEPTION HERE!!!
                    throw new IllegalStateException("View " + view
                            + " has already been added to the window manager.");
                }
            }
            // ...
        }
    }

WindowManagerGlobal是单例的,因此,如果将同一视图两次添加到WindowManagerGlobal,它将崩溃。

我们可以重新处理此异常:

val dlg = AlertDialog.Builder(context).create()
dlg.setView(View.inflate(context, R.layout.layout_dialog_title_sample, null))
dlg.show()
val f = Dialog::class.java.getDeclaredField("mShowing")
f.isAccessible = true
f.setBoolean(dlg, false)
dlg.show()

        dlg = AlertDialog.Builder(context).create()
        dlg?.setView(View.inflate(context, R.layout.layout_dialog_title_sample, null))
        dlg?.show()
        dlg?.dismiss()
        for (i in 1..2) {
            Thread(Runnable {
                Looper.prepare()
                dlg?.show()
                Looper.loop()
            }).start()
        }

上面,我们在调用mShowing以显示对话框“两次”之后更改了字段Dialog#show()。最后,它引发了异常:

    ┌────────────────────────────────────────────────────────────────────────────────────────────────────────────────
    │ main, me.shouheng.suix.SampleApp$customCrash$1.onCrash(SampleApp.kt:64)
    ├┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄
    │ ************* uncaught exception *************
    │ Time Of Crash      : 2020-01-10 14-46-43
    │ Device Manufacturer: OnePlus
    │ Device Model       : ONEPLUS A6000
    │ Android Version    : 9
    │ Android SDK        : 28
    │ App VersionName    : 1.0
    │ App VersionCode    : 1
    │ 
    │ java.lang.IllegalStateException: View DecorView@3a84c11[MainActivity] has already been added to the window manager.
    │   at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:328)
    │   at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:94)
    │   at android.app.Dialog.show(Dialog.java:329)
    │   at me.shouheng.suix.MainActivity$doCreateView$7.onClick(MainActivity.kt:72)
    │   at android.view.View.performClick(View.java:6669)
    │   at android.view.View.performClickInternal(View.java:6638)
    │   at android.view.View.access$3100(View.java:789)
    │   at android.view.View$PerformClick.run(View.java:26145)
    │   at android.os.Handler.handleCallback(Handler.java:873)
    │   at android.os.Handler.dispatchMessage(Handler.java:99)
    │   at android.os.Looper.loop(Looper.java:193)
    │   at android.app.ActivityThread.main(ActivityThread.java:6898)
    │   at java.lang.reflect.Method.invoke(Native Method)
    │   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:537)
    │   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
    └────────────────────────────────────────────────────────────────────────────────────────────────────────────────

因此,解决此问题的最终解决方法是检查是否在不同线程中两次异常显示对话框