Использование нескольких экземпляров одного адаптера массива в нескольких действиях - PullRequest
0 голосов
/ 26 марта 2012

Я работаю над программой для чтения новостей, и у меня есть два основных актива: основной и истории. Main вызывает asynctask и получает все rss-каналы, а затем отображает заголовки после его завершения. Истории отображают статьи из определенных каналов. В главном меню есть навигационная панель, которая называет истории.

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

java.lang.IllegalStateException: содержимое адаптера изменилось, но ListView не получил уведомление. Убедитесь, что содержимое вашего адаптера не изменено из фонового потока, а только из потока пользовательского интерфейса. [в ListView (2131099654, класс android.widget.ListView) с адаптером (класс package.package.ArticleListAdapter)]

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

К сожалению, этот код перефразирован, частично для удобства чтения, а частично потому, что я пишу его для кого-то другого, с закрытым исходным кодом yadda yadda ...

class main{  
  public HashMap<Integer, ArrayList<ArticleHolder>> allArticles;  
  public ArticleListAdapter ArtListAdapter;  
  public void onCreate(Bundle savedInstanceState) {  
     allArticles = new HashMap<Integer, ArrayList<ArticleHolder>>();
     myApp appstate = (myApp)getApplicationContext();  
     appState.setParsedArticles(allArticles); //Added this for universal availability of the articles
     //download things  
     //background.execute();  
     //...  

  }  

 private class downloader extends Asynctask ...{  
 ...  
 onPostExecute(){
    ArticleListAdapter = new ArticleListAdapter(context c, list_item L, allArticles.get(1));
    listView1 = (ListView)findViewById(R.id.listView1);
    listView1.setAdapter(ArtListAdapter);
   }
 }


class stories{  
  public HashMap<Integer, ArrayList<ArticleHolder>> allArticles;  
  public ArticleListAdapter ArtListAdapter;  

  public void onCreate(Bundle savedInstanceState) {  
    myApp appstate = (myApp)getApplicationContext();
    allArticles = appState.getParsedArticles();
    //set layout
    //get article to display from Bundle extras
    ListView LV = (ListView) findViewById(R.id.listView1);
    ArtListAdapter = new ArticleListAdapter(StoriesScreenActivity.this, R.layout.article_list_item, allCleanArticles.get(buttonFeedNum));
    LV = (ListView)findViewById(R.id.listView1);
    LV.setAdapter(ArtListAdapter);
    }
}

Код для адаптера следующий и точный:

public class ArticleListAdapter extends ArrayAdapter<ArticleHolder>{
    private static ArrayList<ArticleHolder> ArticleList;
    private Context context; 
    private LayoutInflater mInflater;

    public ArticleListAdapter(Context pcontext, int layoutResourceId, ArrayList<ArticleHolder> results) {
        super(pcontext, layoutResourceId, results);
        context = pcontext;
        ArticleList = results;
        mInflater = LayoutInflater.from(context);
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.article_list_item, null);
            holder = new ViewHolder();
            holder.txtMain = (TextView) convertView.findViewById(R.id.textView1);
            holder.txtblurb = (TextView) convertView.findViewById(R.id.textView2);
            holder.pic_view = (ImageView) convertView.findViewById(R.id.imageView1);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        holder.txtMain.setText(ArticleList.get(position).getTitle());
        holder.txtblurb.setText(ArticleList.get(position).getMainText());
        holder.pic_view.setContentDescription(context.getString(R.string.GenImgDesc));
        UrlImageViewHelper.setUrlDrawable(holder.pic_view, ArticleList.get(position).getPicName(),R.drawable.ic_placeholder);

        return convertView;
    }

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

    public ArticleHolder getItem(int position) {
        return ArticleList.get(position);
    }

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

    static class ViewHolder {
        TextView txtMain;
        TextView txtblurb;
        ImageView pic_view;
    }

}

Спасибо за вашу помощь, я действительно застрял.
Также большое спасибо и благодарим koush и Jwsonic на Github за их работу над UrlImageViewer. Это круто.

Edit: Вот мой AsyncTask.doInBackground (). Извините, что так долго, я был на некоторое время без моего компьютера. Еще раз спасибо за вашу помощь.

protected Boolean doInBackground(String... params) {
    boolean succeeded = false;
    String downloadPath = null;

    for(Integer num: feedArray){
        downloadPath = "example.com/rss/"+Integer.toString(num);
        doSax(downloadPath, num);
    }
    for(Integer num: feedArray){
        currentDirtyFeedArticles = allDirtyArticles.get(num);
        for(ArticleHolder dirtyArticle: currentDirtyFeedArticles){
            dirtyArticle.setTitle(textCleaner(dirtyArticle.getTitle()));

            //some text cleaning to make it look pretty

            }
        }
        succeeded = true;
        return succeeded;
}

Хорошо, поэтому я воспользовался советом Jedi_warriors и попытался добавить notifyDataSetChanged (), но я не мог понять, как получить его в соответствии с моим пользовательским адаптером. Это поставило меня на правильный путь, хотя я понял, что представление списка на домашнем экране не обновлялось, когда я вернулся к нему. Это заставило меня взглянуть на наличие метода onResume, и после некоторых проб и ошибок я в итоге вызвал код, чтобы связать представление с адаптером в onResume. Хитрость заключалась в том, что приложение закрывалось при открытии, потому что этот код не был готов, поэтому я запретил запуск кода в onResume до тех пор, пока приложение не будет готово к работе. Насколько я могу судить, похоже, это решило проблему. Спасибо за вашу помощь!

1 Ответ

1 голос
/ 26 марта 2012

использование в асинхронном режиме:

@Override
    protected Void doInBackground(String... arg0) {
        // TODO Auto-generated method stub

    }

потому что это имеет доступ к Ui. А для ListView используйте listview.notifyDataSetChanged ();

надеюсь, это поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...