Android应用程序有时会在启动时崩溃

时间:2014-01-03 20:51:21

标签: android android-asynctask crash

我的Android应用程序存在问题。 有时它会在启动时崩溃,但有时却没有。 可悲的是,LogCat并没有帮助我,我也不知道出了什么问题。

我的应用使用AsyncTask从互联网上获取和处理数据。

什么可能导致问题?

这是LogCat日志:

01-03 21:43:29.998: D/AbsListView(28500): Get MotionRecognitionManager
01-03 21:43:30.008: D/ProgressBar(28500): setProgress = 0
01-03 21:43:30.008: D/ProgressBar(28500): setProgress = 0, fromUser = false
01-03 21:43:30.008: D/ProgressBar(28500): mProgress = 0mIndeterminate = false, mMin = 0, mMax = 10000
01-03 21:43:30.038: D/AbsListView(28500): onVisibilityChanged() is called, visibility : 4
01-03 21:43:30.038: D/AbsListView(28500): unregisterIRListener() is called 
01-03 21:43:30.038: D/AbsListView(28500): onVisibilityChanged() is called, visibility : 0
01-03 21:43:30.038: D/AbsListView(28500): unregisterIRListener() is called 
01-03 21:43:30.179: D/libEGL(28500): loaded /vendor/lib/egl/libEGL_adreno.so
01-03 21:43:30.189: D/libEGL(28500): loaded /vendor/lib/egl/libGLESv1_CM_adreno.so
01-03 21:43:30.189: D/libEGL(28500): loaded /vendor/lib/egl/libGLESv2_adreno.so
01-03 21:43:30.189: I/Adreno-EGL(28500): <qeglDrvAPI_eglInitialize:316>: EGL 1.4 QUALCOMM build:  (CL4169980)
01-03 21:43:30.189: I/Adreno-EGL(28500): OpenGL ES Shader Compiler Version: 17.01.10.SPL
01-03 21:43:30.189: I/Adreno-EGL(28500): Build Date: 09/26/13 Thu
01-03 21:43:30.189: I/Adreno-EGL(28500): Local Branch: 
01-03 21:43:30.189: I/Adreno-EGL(28500): Remote Branch: 
01-03 21:43:30.189: I/Adreno-EGL(28500): Local Patches: 
01-03 21:43:30.189: I/Adreno-EGL(28500): Reconstruct Branch: 
01-03 21:43:30.239: D/OpenGLRenderer(28500): Enabling debug mode 0
01-03 21:43:30.239: D/ProgressBar(28500): updateDrawableBounds: left = 0
01-03 21:43:30.239: D/ProgressBar(28500): updateDrawableBounds: top = 0
01-03 21:43:30.239: D/ProgressBar(28500): updateDrawableBounds: right = 144
01-03 21:43:30.239: D/ProgressBar(28500): updateDrawableBounds: bottom = 144
01-03 21:43:30.239: D/AbsListView(28500): unregisterIRListener() is called 
01-03 21:43:30.249: D/AbsListView(28500): unregisterIRListener() is called 
01-03 21:43:30.479: D/AndroidRuntime(28500): Shutting down VM
01-03 21:43:30.479: W/dalvikvm(28500): threadid=1: thread exiting with uncaught exception (group=0x418c6898)
01-03 21:43:30.489: E/AndroidRuntime(28500): FATAL EXCEPTION: main
01-03 21:43:30.489: E/AndroidRuntime(28500): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(2131427329, class android.widget.ListView) with Adapter(class se.taby10.application.NewsList)]
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.widget.ListView.layoutChildren(ListView.java:1557)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.widget.AbsListView.onLayout(AbsListView.java:2444)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.View.layout(View.java:15204)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.ViewGroup.layout(ViewGroup.java:4793)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1076)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.View.layout(View.java:15204)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.ViewGroup.layout(ViewGroup.java:4793)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.View.layout(View.java:15204)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.ViewGroup.layout(ViewGroup.java:4793)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at com.android.internal.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:349)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.View.layout(View.java:15204)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.ViewGroup.layout(ViewGroup.java:4793)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.widget.FrameLayout.onLayout(FrameLayout.java:448)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.View.layout(View.java:15204)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.ViewGroup.layout(ViewGroup.java:4793)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2258)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2005)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1247)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6355)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:791)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.Choreographer.doCallbacks(Choreographer.java:591)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.Choreographer.doFrame(Choreographer.java:561)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:777)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.os.Handler.handleCallback(Handler.java:730)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.os.Handler.dispatchMessage(Handler.java:92)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.os.Looper.loop(Looper.java:137)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at android.app.ActivityThread.main(ActivityThread.java:5419)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at java.lang.reflect.Method.invokeNative(Native Method)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at java.lang.reflect.Method.invoke(Method.java:525)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
01-03 21:43:30.489: E/AndroidRuntime(28500):    at dalvik.system.NativeStart.main(Native Method)
01-03 21:43:33.262: I/Process(28500): Sending signal. PID: 28500 SIG: 9

代码:

package se.taby10.application;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager;
import android.text.Html;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;

public class MainActivity extends Activity {

    Button btnWebsite, btnCourses;
    ListView newsList;
    ArrayList<Item> newsArrayList;
    ArrayAdapter<Item> newsAdapter;
    Context context;
    SharedPreferences settings;
    String feedUrl = "http://taby10.se/feed.php?encoding=json";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = this;
        newsList = (ListView) findViewById(R.id.newsList);
        settings = PreferenceManager
                .getDefaultSharedPreferences(getBaseContext());

        newsArrayList = new ArrayList<Item>();
        newsAdapter = new NewsList(MainActivity.this, newsArrayList);

        newsList.setAdapter(newsAdapter);
        newsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view,
                    int position, long id) {

                // Set up intent and pass item data
                Intent intent = new Intent("se.taby10.application.SINGLENEWS");

                intent.putExtra("ItemId", newsArrayList.get(position).getId());
                intent.putExtra("ItemTitle", newsArrayList.get(position)
                        .getTitle());
                intent.putExtra("ItemContent", newsArrayList.get(position)
                        .getContent());
                intent.putExtra("ItemTimestamp", newsArrayList.get(position)
                        .getTimestamp());
                intent.putExtra("ItemUrl", newsArrayList.get(position).getUrl());

                // Start activity to show news in
                startActivity(intent);
            }
        });

        // Buttons
        btnWebsite = (Button) findViewById(R.id.btnWebsite);
        btnWebsite.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Intent websiteIntent = new Intent(Intent.ACTION_VIEW);
                websiteIntent.setData(Uri.parse("http://taby10.se"));
                startActivity(websiteIntent);
            }
        });

        btnCourses = (Button) findViewById(R.id.btnCourses);
        btnCourses.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                Intent coursesIntent = new Intent(Intent.ACTION_VIEW);
                coursesIntent.setData(Uri.parse("http://taby10.se/courses"));
                startActivity(coursesIntent);
            }
        });

        // Load feed
        NewsListTask loaderTask = new NewsListTask();
        loaderTask.execute();

        refresh();

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_about:
            startActivity(new Intent("se.taby10.application.ABOUT"));
            break;
        case R.id.action_settings:
            startActivity(new Intent("se.taby10.application.SETTINGS"));
            break;
        }
        return false;
    }

    public void refresh() {
        int updateFrequency = settings.getInt("updatefrequency", 600);

        if (updateFrequency != 0) {
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {

                    // Reload news feed
                    NewsListTask loaderTask = new NewsListTask();
                    loaderTask.execute();

                    // Reset timer
                    refresh();
                }
            }, updateFrequency * 1000);
        }
    }

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

        ProgressDialog dialog;

        @Override
        protected void onPreExecute() {
            dialog = new ProgressDialog(context);
            dialog.setTitle("Hämtar nyheter");
            dialog.setMessage("Vänta medan nyheter laddas. Detta kan ta ett tag.");
            dialog.setCancelable(false);
            dialog.show();
            super.onPreExecute();
        }

        @Override
        protected Void doInBackground(Void... params) {
            HttpClient client = new DefaultHttpClient();
            HttpGet getRequest = new HttpGet(feedUrl);

            try {
                HttpResponse response = client.execute(getRequest);
                StatusLine statusLine = response.getStatusLine();
                int statusCode = statusLine.getStatusCode();

                if (statusCode != 200) {
                    return null;
                }

                InputStream jsonStream = response.getEntity().getContent();
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(jsonStream));
                StringBuilder builder = new StringBuilder();
                String line;

                while ((line = reader.readLine()) != null) {
                    builder.append(line);
                }

                String jsonData = builder.toString();
                JSONArray json = new JSONArray(jsonData);

                // Get items from json
                for (int i = 0; i < json.length(); i++) {
                    JSONObject e = json.getJSONObject(i);

                    Item objItem = new Item();

                    objItem.setId(e.getInt("id"));
                    objItem.setTitle(Html.fromHtml(
                            Html.fromHtml(e.getString("title")).toString())
                            .toString());
                    objItem.setDescription(Html.fromHtml(
                            Html.fromHtml(e.getString("description"))
                                    .toString()).toString());
                    objItem.setContent(Html.fromHtml(
                            Html.fromHtml(e.getString("content")).toString())
                            .toString());
                    objItem.setTimestamp(Html
                            .fromHtml(e.getString("timestamp")).toString());
                    objItem.setUrl(Html.fromHtml(e.getString("link"))
                            .toString());

                    newsArrayList.add(objItem); // Add item to list
                }

            } catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            dialog.dismiss();
            newsAdapter.notifyDataSetChanged();
            super.onPostExecute(result);
        }
    }

}

1 个答案:

答案 0 :(得分:0)

好的,你有某种List为你的适配器提供数据? 如果是这种情况,则不应在其他线程中修改它。你应该获取数据,当你有新的List时,然后将它传递给适配器并调用notifydatasetchanged方法来更新它。

logcat表示您正在更改适配器的数据而不通知!