3

明らかなパターンのないランダムなクラッシュ。ListView を開くと、数回 (ランダム) に 1 回、次のエラーでアプリケーションがクラッシュします。 学ぶべきことがたくさんあるので、それが非常に明らかな間違いである場合はご容赦ください。

エラーログキャット

W/dalvikvm( 9445): threadid=1: thread exiting with uncaught exception (group=0x40018578)

E/AndroidRuntime( 9445): FATAL EXCEPTION: main

E/AndroidRuntime( 9445): 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(2131361795, class android.widget.ListView) with Adapter(class gst.sies.popatt.LazyAdapter)]

E/AndroidRuntime( 9445):    at android.widget.ListView.layoutChildren(ListView.java:1545)

E/AndroidRuntime( 9445):    at android.widget.AbsListView.onLayout(AbsListView.java:1422)

E/AndroidRuntime( 9445):    at android.view.View.layout(View.java:7175)

E/AndroidRuntime( 9445):    at android.widget.RelativeLayout.onLayout(RelativeLayout.java:912)

E/AndroidRuntime( 9445):    at android.view.View.layout(View.java:7175)

E/AndroidRuntime( 9445):    at android.widget.FrameLayout.onLayout(FrameLayout.java:338)

E/AndroidRuntime( 9445):    at android.view.View.layout(View.java:7175)

E/AndroidRuntime( 9445):    at android.widget.FrameLayout.onLayout(FrameLayout.java:338)

E/AndroidRuntime( 9445):    at android.view.View.layout(View.java:7175)

E/AndroidRuntime( 9445):    at android.view.ViewRoot.performTraversals(ViewRoot.java:1146)

E/AndroidRuntime( 9445):    at android.view.ViewRoot.handleMessage(ViewRoot.java:1865)

E/AndroidRuntime( 9445):    at android.os.Handler.dispatchMessage(Handler.java:99)

E/AndroidRuntime( 9445):    at android.os.Looper.loop(Looper.java:130)

E/AndroidRuntime( 9445):    at android.app.ActivityThread.main(ActivityThread.java:3687)

E/AndroidRuntime( 9445):    at java.lang.reflect.Method.invokeNative(Native Method)

E/AndroidRuntime( 9445):    at java.lang.reflect.Method.invoke(Method.java:507)

E/AndroidRuntime( 9445):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)

E/AndroidRuntime( 9445):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)

E/AndroidRuntime( 9445):    at dalvik.system.NativeStart.main(Native Method)

D/dalvikvm( 9445): GC_CONCURRENT freed 473K, 50% free 3063K/6023K, external 714K/1025K, paused 4ms+5ms

E/liblog  ( 1475): failed to call dumpstate

E/        ( 1475): Dumpstate > /data/log/dumpstate_app_error

D/InputReader( 1475): Input event: value=1

D/InputReader( 1475): Input event: value=0

D/InputReader( 1475): Input event: value=1

コード

package gst.sies.popatt;

import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class GalleryActivity extends Activity
{
    static final String KEY_ID = "id";
    static final String KEY_TITLE = "title";
    static final String KEY_THUMB_URL = "thumb_url";
    public Typeface myTypeface;
    private ArrayList<HashMap<String, String>> nomineeList;
    private ListView n_list;
    private Intent back_button;
    private String[] category;
    private LazyAdapter adapter;
    private int category_index;
    private SQLiteDatabase db;
    private SharedPreferences prefs;
    private TextView voted;
    private UserLoginTask getNominees;
    private ImageView iv;
    private boolean date;
    int i=0;

    @SuppressLint("SdCardPath")
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        String title = getIntent().getStringExtra("title");

        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
        {
            this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        }
        else
            this.setTitle(title);
        setContentView(R.layout.activity_gallery);
        myTypeface = Typeface.createFromAsset(
                this.getAssets(),
                "ROBOTO.TTF");

        prefs= new ObscuredSharedPreferences( 
                GalleryActivity.this, GalleryActivity.this.getSharedPreferences("gst.sies.popatt", Context.MODE_PRIVATE) );

        back_button= new Intent (GalleryActivity.this, CategoriesActivity.class);
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
            voted = (TextView) findViewById(R.id.textView3);
        else
            voted = (TextView) findViewById(R.id.TextView_14);
        iv= (ImageView) findViewById(R.id.voted_thumbnail);
        category_index = getIntent().getIntExtra("category_index", 0);
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
        {
            TextView tv = (TextView) findViewById(R.id.textView1);
            tv.setTypeface(myTypeface);
            tv.setText(title);

            voted.setTypeface(myTypeface);
        }

        if(prefs.getString(Integer.toString(category_index), "NA").equals("NA"))
            voted.setText("Voted for: No One");
        else
        {
            iv.setImageResource(R.drawable.radio_checked);
            //voted.setText("Voted for: "+ prefs.getString(Integer.toString(category_index), "No One"));
            voted.setText("can't do it yet ;)");
            voted.setSelected(true);
        }

        Calendar now = Calendar.getInstance();
        if(now.get(Calendar.DATE) >= 1 && now.get(Calendar.DATE) <= 18)
            date = true;
        else
            date = false;

        nomineeList = new ArrayList<HashMap<String, String>>();
        File nom_db = new File (Environment.getExternalStorageDirectory()+"/Android/data/gst.sies.popatt/databases/nominees.db");

        db = SQLiteDatabase.openOrCreateDatabase(nom_db, null);

        getNominees = new UserLoginTask();
        getNominees.execute((Void) null);

        n_list = (ListView) findViewById(R.id.nominee_list);    

        adapter=new LazyAdapter(this, nomineeList);
        adapter.notifyDataSetChanged();

        n_list.setAdapter(adapter);

        n_list.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position,
                    long id) {
                String votedOne = (String) ((TextView) view.findViewById(R.id.title)).getText();
                prefs.edit().putString(Integer.toString(category_index), votedOne).commit();
                if(date)
                voted.setText("Voted for: "+ votedOne);
                else
                voted.setText("can't do it yet ;)");

                voted.setSelected(true);
                iv.setImageResource(R.drawable.radio_checked);
            }
        });
    }
    @Override
    public void onBackPressed()
    {
        startActivity(back_button);
        finish();
    }

    public boolean isTableExists(String tableName) {
        Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '"+tableName+"'", null);
        if(cursor!=null) {
            if(cursor.getCount()>0) {
                cursor.close();
                return true;
            }
            cursor.close();
        }
        return false;
    }
    public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Void... params) {
            Resources res = getResources();
            category = res.getStringArray(R.array.category_list_short);
            if(isTableExists(category[category_index]) && date)
            {
                Cursor c = db.rawQuery("SELECT * FROM "+category[category_index]+" WHERE name IS NOT NULL", null);
                if(c.moveToFirst())
                {
                    while(!c.isAfterLast())
                    {   
                        HashMap<String, String> map = new HashMap<String, String>();

                        map.put(KEY_ID, c.getString(0));
                        map.put(KEY_TITLE, c.getString(c.getColumnIndex("name")));
                        map.put(KEY_THUMB_URL, c.getString(c.getColumnIndex("url")));
                        nomineeList.add(map);
                        c.moveToNext();
                    }
                    c.close();

                    return true;
                }   
            }
            else
            {
                for (int i = 0; i < 10 ; i++) {

                HashMap<String, String> map = new HashMap<String, String>();

                map.put(KEY_ID, Integer.toString(i));
                map.put(KEY_TITLE, "No Name Available");
                map.put(KEY_THUMB_URL, "https://fbcdn-sphotos-d-a.akamaihd.net/hphotos-ak-snc6/5939_10151499921443518_604230176_s.jpg");
                nomineeList.add(map);
                }
                return true;
            }
            return true;
        }

        @Override
        protected void onPostExecute(Boolean success) {
            super.onPostExecute(success);
            runOnUiThread(new Runnable() {
                 public void run() {
                     db.close();
                     adapter.notifyDataSetChanged();
                }
            });
        }

        @Override
        protected void onCancelled() {

        }
        @Override
        protected void onPreExecute()
        {       }
    }
}

アダプタ クラス

package gst.sies.popatt;

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

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class LazyAdapter extends BaseAdapter {

    private Activity activity;
    private ArrayList<HashMap<String, String>> data;
    private static LayoutInflater inflater=null;
    public ImageLoader imageLoader; 

    public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
        activity = a;
        data=d;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        imageLoader=new ImageLoader(activity.getApplicationContext());
        //rbState =  new boolean [100];
    }
    public int getCount() {
        return data.size();
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        View vi=convertView;
        if(convertView==null)
            vi = inflater.inflate(R.layout.rowview, null);
        TextView title = (TextView)vi.findViewById(R.id.title); // title
        ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // thumb image
        GalleryActivity gl = new GalleryActivity();
        title.setTypeface(gl.myTypeface);
        HashMap<String, String> nominee = new HashMap<String, String>();
        nominee = data.get(position);
        title.setText(nominee.get(GalleryActivity.KEY_TITLE));
        imageLoader.DisplayImage(nominee.get(GalleryActivity.KEY_THUMB_URL),R.drawable.ic_launcher, thumb_image);
        return vi;    
    }

}

何が問題なのか見当がつかないので、正直に言うとあまり試していません。

編集:更新されたコード

package gst.sies.popatt;

import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class GalleryActivity extends Activity
{
    static final String KEY_ID = "id";
    static final String KEY_TITLE = "title";
    static final String KEY_THUMB_URL = "thumb_url";
    public Typeface myTypeface;
    private ArrayList<HashMap<String, String>> nomineeList;
    private ListView n_list;
    private Intent back_button;
    private String[] category;
    private LazyAdapter adapter;
    private int category_index;
    private SQLiteDatabase db;
    private SharedPreferences prefs;
    private TextView voted;
    private UserLoginTask getNominees;
    private ImageView iv;
    private boolean date;
    int i=0;

    @SuppressLint("SdCardPath")
    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        String title = getIntent().getStringExtra("title");

        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
        {
            this.requestWindowFeature(Window.FEATURE_NO_TITLE);
        }
        else
            this.setTitle(title);
        setContentView(R.layout.activity_gallery);
        myTypeface = Typeface.createFromAsset(
                this.getAssets(),
                "ROBOTO.TTF");

        prefs= new ObscuredSharedPreferences( 
                GalleryActivity.this, GalleryActivity.this.getSharedPreferences("gst.sies.popatt", Context.MODE_PRIVATE) );

        back_button= new Intent (GalleryActivity.this, CategoriesActivity.class);
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
            voted = (TextView) findViewById(R.id.textView3);
        else
            voted = (TextView) findViewById(R.id.TextView_14);
        iv= (ImageView) findViewById(R.id.voted_thumbnail);
        category_index = getIntent().getIntExtra("category_index", 0);
        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
        {
            TextView tv = (TextView) findViewById(R.id.textView1);
            tv.setTypeface(myTypeface);
            tv.setText(title);

            voted.setTypeface(myTypeface);
        }

        if(prefs.getString(Integer.toString(category_index), "NA").equals("NA"))
            voted.setText("Voted for: No One");
        else
        {
            iv.setImageResource(R.drawable.radio_checked);
            //voted.setText("Voted for: "+ prefs.getString(Integer.toString(category_index), "No One"));
            voted.setText("can't do it yet ;)");
            voted.setSelected(true);
        }

        Calendar now = Calendar.getInstance();
        if(now.get(Calendar.DATE) >= 1 && now.get(Calendar.DATE) <= 18)
            date = true;
        else
            date = false;

        nomineeList = new ArrayList<HashMap<String, String>>();
        File nom_db = new File (Environment.getExternalStorageDirectory()+"/Android/data/gst.sies.popatt/databases/nominees.db");

        db = SQLiteDatabase.openOrCreateDatabase(nom_db, null);

        getNominees = new UserLoginTask();
        getNominees.execute((Void) null);

        n_list = (ListView) findViewById(R.id.nominee_list);    

        adapter=new LazyAdapter(this, nomineeList);
        n_list.setAdapter(adapter);
        adapter.notifyDataSetChanged();

        n_list.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position,
                    long id) {
                String votedOne = (String) ((TextView) view.findViewById(R.id.title)).getText();
                prefs.edit().putString(Integer.toString(category_index), votedOne).commit();
                if(date)
                voted.setText("Voted for: "+ votedOne);
                else
                voted.setText("can't do it yet ;)");

                voted.setSelected(true);
                iv.setImageResource(R.drawable.radio_checked);
            }
        });
    }
    @Override
    public void onBackPressed()
    {
        startActivity(back_button);
        finish();
    }

    public boolean isTableExists(String tableName) {
        Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '"+tableName+"'", null);
        if(cursor!=null) {
            if(cursor.getCount()>0) {
                cursor.close();
                return true;
            }
            cursor.close();
        }
        return false;
    }
    public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Void... params) {
            Resources res = getResources();
            category = res.getStringArray(R.array.category_list_short);
            if(isTableExists(category[category_index]) && date)
            {
                Cursor c = db.rawQuery("SELECT * FROM "+category[category_index]+" WHERE name IS NOT NULL", null);
                if(c.moveToFirst())
                {
                    while(!c.isAfterLast())
                    {   
                        HashMap<String, String> map = new HashMap<String, String>();

                        map.put(KEY_ID, c.getString(0));
                        map.put(KEY_TITLE, c.getString(c.getColumnIndex("name")));
                        map.put(KEY_THUMB_URL, c.getString(c.getColumnIndex("url")));
                        nomineeList.add(map);
                        c.moveToNext();
                    }
                    c.close();

                    return true;
                }   
            }
            else
            {
                for (int i = 0; i < 10 ; i++) {

                HashMap<String, String> map = new HashMap<String, String>();

                map.put(KEY_ID, Integer.toString(i));
                map.put(KEY_TITLE, "No Name Available");
                map.put(KEY_THUMB_URL, "https://fbcdn-sphotos-d-a.akamaihd.net/hphotos-ak-snc6/5939_10151499921443518_604230176_s.jpg");
                nomineeList.add(map);
                }
                return true;
            }
            return true;
        }

        @Override
        protected void onPostExecute(Boolean success) {
            super.onPostExecute(success);
            db.close();
        }

        @Override
        protected void onCancelled() {

        }
        @Override
        protected void onPreExecute()
        {       }
    }
}
4

1 に答える 1

2

アダプターをリストビューに設定した後、notifyDataSetChanged()を呼び出し ます。

  adapter=new LazyAdapter(this, nomineeList)
        n_list.setAdapter(adapter);
   adapter.notifyDataSetChanged();

LazyAdapter データに変更がない場合でも、notifyDataSetChanged() を呼び出しているため

adapter=new LazyAdapter(this, nomineeList);
        adapter.notifyDataSetChanged();

notifyDataSetChanged() - アダプター内のデータが変更されたという通知をリストビューに通知します。listView にまだバインドされていない Adapter で notifyDataSetChanged() を呼び出そうとすると、この例外がスローされます。

java.lang.IllegalStateException: アダプターの内容が変更されましたが、ListView は通知を受け取りませんでした。アダプターのコンテンツがバックグラウンド スレッドからではなく、UI スレッドからのみ変更されていることを確認してください。

于 2013-03-31T14:27:30.790 に答える