简体   繁体   中英

App crashes on android 4.0+

I have and android app that works on android 4.0 great, but it crashes on android 4.3 and 4.4. I get this from the logCat

01-11 14:40:27.669: E/ACRA(25835): ACRA caught a IllegalStateException exception for quran. Building report.
01-11 14:40:27.789: E/AndroidRuntime(25835): 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(2131099688, class android.widget.ListView) with Adapter(class quran.functions.PlaylistAdapter)]

Here is my code:

public class Playlist extends FragmentActivity {

    private ListView list;
    private Button manager, downloadAll;
    private TextView reciter;
    public static PlaylistAdapter adapter;
    private ArrayList<Songs> songs;
    private int RECITER_ID;
    private String url, title, label;
    private SlidingMenu slidingMenu;
    private DatabaseHelper db;
    private ImageView nowPlaying, back;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.playlist);
        initWidgets();
        list.setOnItemClickListener(new OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1,
                    int position, long arg3) {

                Intent intent = new Intent(Playlist.this, PlayerFinal.class);
                intent.putExtra("songs", songs);
                if (getIntent().getIntExtra("duaa", -1) == 115)
                    intent.putExtra("lang", 115);
                intent.putExtra("position", position);
                intent.putExtra("fromClass", this.getClass() + "");
                // intent.putExtra("mp3link", mp3link);
                startActivity(intent);
            }
        });
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {

                XmlMapParser m = new XmlMapParser(Playlist.this, RECITER_ID);
                HashMap<String, ArrayList<String>> map = m.convert();
                map.keySet();
                label = map.get("RecitorLabel").get(0);
                title = map.get("Title").get(0);
                url = map.get("Link").get(0);
                back = (ImageView) findViewById(R.id.playlist_back);
                back.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View arg0) {
                        finish();
                    }
                });
                db.openDB();
                for (int i = 1; i < map.get("Link").size(); i++) {
                    if (db.isDownloaded(i, title, RECITER_ID)) {
                        songs.add(new Songs(i, map.get("Title").get(i),
                                Environment.getExternalStorageDirectory()
                                        .getPath()
                                        + "/"
                                        + getString(R.string.app_name)
                                        + "/"
                                        + title
                                        + "/"
                                        + map.get("Title").get(i)
                                        + ".mp3", title, true, RECITER_ID,
                                false));

                    } else
                        songs.add(new Songs(i, map.get("Title").get(i), url
                                + label + "/"
                                + new DecimalFormat("000").format(i) + ".mp3",
                                title, false, RECITER_ID, false));
                }
                db.closeDB();
                // Log.v("--",m.convert().get("Link").get(1));
                // [RecitorLabel, Title, Link] THIS ARE THE KEYS m

                // Log.v("--", map.get("RecitorLabel").get(0));
                // Log.v("--", map.get("Link").get(1));
                return null;
            }

            protected void onPostExecute(Void result) {
                adapter = new PlaylistAdapter(Playlist.this, songs);
                list.setAdapter(adapter);
                reciter.setText(songs.get(0).getRecitorName());
            };
        }.execute();

    }

    @Override
    public void onBackPressed() {
        if (slidingMenu.isMenuShowing()) {
            slidingMenu.toggle();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        try {
            if (Tplayer.getInstance().isPlaying()) {
                adapter = new PlaylistAdapter(this, songs);
                list.setAdapter(adapter);
                adapter.notifyDataSetChanged();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU) {
            this.slidingMenu.toggle();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case android.R.id.home:
            this.slidingMenu.toggle();
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    private void initWidgets() {
        db = new DatabaseHelper(this);
        manager = (Button) findViewById(R.id.playlist_download_manager);
        manager.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Playlist.this, DownloadManager.class);
                startActivity(intent);
            }
        });
        reciter = (TextView) findViewById(R.id.playlist_reciter_name_top);
        list = (ListView) findViewById(R.id.playlist_list);
        downloadAll = (Button) findViewById(R.id.playlist_download_all);
        manager = (Button) findViewById(R.id.playlist_download_manager);
        songs = new ArrayList<Songs>();
        RECITER_ID = getIntent().getIntExtra("filename", -1);
        // downloadAll.setOnClickListener(new OnClickListener() {
        //
        // @Override
        // public void onClick(View v) {
        // new DownloadAll(Playlist.this, songs);
        // db.openDB();
        // for (int i = 0; i < songs.size(); i++) {
        // db.addDownloaded(songs.get(i).getNumber(), songs.get(i)
        // .getLink(), 0, songs.get(i).getRecitorID(), "",
        // songs.get(i).getTitle());
        // }
        // db.closeDB();
        // }
        // });
        nowPlaying = (ImageView) findViewById(R.id.playlist_now_playing);
        nowPlaying.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Tplayer tplayer = Tplayer.getInstance();
                if (tplayer.isPlaying()) {
                    Intent intent = new Intent(Playlist.this, PlayerFinal.class);
                    if (tplayer.isPlaying())
                        intent.putExtra("songs", tplayer.getSongs());
                    else
                        intent.putExtra("songs", songs);
                    if (tplayer.getSongs().size() == 14)
                        intent.putExtra("lang", 115);
                    intent.putExtra("position", tplayer.getPosition());
                    startActivity(intent);
                }
            }
        });
        // Jeremy Feinstein slidinglistadapter line 94
        slidingMenu = new SlidingMenu(this);
        slidingMenu.setMode(SlidingMenu.LEFT);
        slidingMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN);
        slidingMenu.setShadowWidthRes(R.dimen.slidingmenu_shadow_width);
        slidingMenu.setShadowDrawable(R.drawable.slidingmenu_shadow);
        slidingMenu.setBehindOffsetRes(R.dimen.slidingmenu_offset);
        slidingMenu.setFadeDegree(0.35f);
        slidingMenu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT);
        slidingMenu.setMenu(R.layout.slidingmenu);

    }

}

and my playlist adapter class:

public class PlaylistAdapter extends BaseAdapter {

    private Activity activity;
    private static LayoutInflater inflater = null;
    private ArrayList<Songs> data;
    private DatabaseHelper db;
    private SharedPreferences prefs;
    int playpos;
    int recitorID;

    public PlaylistAdapter(Activity a, ArrayList<Songs> songs) {
        activity = a;
        data = songs;
        db = new DatabaseHelper(a);
        inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        prefs = activity.getSharedPreferences("quantic.Quran",
                Context.MODE_PRIVATE);
        recitorID = prefs.getInt("recID", -1);
        playpos = prefs.getInt("posPlaying", -1);
    }

    public int getCount() {
        return data.size();
    }

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

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

    public View getView(final int position, View convertView,
            final ViewGroup parent) {
        View vi = convertView;
        if (convertView == null)
            vi = inflater.inflate(R.layout.song_item, parent, false);

        ImageView download = (ImageView) vi
                .findViewById(R.id.playlist_item_download);
        db.openDB();
        if (db.isDownloaded(data.get(position).getNumber(), data.get(position)
                .getRecitorName(), data.get(position).getRecitorID()))
            download.setImageResource(R.drawable.download_yes);
        else {
            download.setImageResource(R.drawable.download_no);
            download.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {

                    new DownloadFileFromURL(activity, data.get(position)
                            .getRecitorName(), data.get(position).getTitle(),
                            data.get(position).getLink(), data.get(position)
                                    .getNumber(), data.get(position)
                                    .getRecitorID()).execute();
                    if (!db.isDBOpen())
                        db.openDB();
                    db.addDownloaded(data.get(position).getNumber(),
                            data.get(position).getLink(), 0, data.get(position)
                                    .getRecitorID(), "", data.get(position)
                                    .getTitle());

                    Toast.makeText(activity,
                            "Downloading " + data.get(position).getTitle(),
                            Toast.LENGTH_SHORT).show();

                }
            });
        }
        db.closeDB();

        TextView number = (TextView) vi.findViewById(R.id.playlist_item_num);
        TextView reciterName = (TextView) vi
                .findViewById(R.id.playlist_item_reciterName);
        reciterName.setText(data.get(position).getRecitorName());
        if (activity.getClass() == Playlist.class) {
            reciterName.setVisibility(View.GONE);
        }
        TextView title = (TextView) vi.findViewById(R.id.playlist_item_reciter);
        title.setText(data.get(position).getTitle());
        number.setText((position + 1) + "");
        ImageView eq = (ImageView) vi.findViewById(R.id.playlist_item_equlizer);
        if (Tplayer.getInstance().isPlaying())
            if (Tplayer.getInstance().getPosition() == position
                    && data.get(position).getRecitorID() == Tplayer
                            .getInstance().getSong().getRecitorID()) {
                eq.setVisibility(View.VISIBLE);
                Ion.with(eq).load("http://darkodev.info/quran/dots.gif");
            } else {
                eq.setVisibility(View.GONE);
            }

        return vi;
    }
}

Very old question, but no answer. I'm sure you have found a fix by now, but anyway.

You're changing the songs list object in background, and if Android decides to redraw your list (user scrolls your list), effectively accessing the songs list object, it may have changed and cause this exception to be thrown.

You need to use a temporary songs list and create a new adapter with it to update your list, thus not changing the current adapter list until you set a new adapter from the main UI thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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