私はニュースリーダーに取り組んでおり、メインとストーリーという 2 つの主要なアクティビティがあります。Main は asynctask を呼び出し、すべての rss フィードを取得し、完了すると見出しを表示します。ストーリーには、特定のフィードの記事が表示されます。ストーリーを呼び出すメインのナビゲーションバーがあります。
ダウンロードして解析した記事は、フィードの配列リストのハッシュマップにあります。私が持っているアダプター クラスは、arrayAdapter の 1 つだけです。すべてが正常に機能し、新しいリストビューを作成するたびに arrayAdapter の個別のインスタンスを作成しますが、問題は、ストーリーからメインに戻ってリスト内の何かをクリックするときです。特に、ストーリーの項目が見出しよりも少ない場合に発生します。主に、次のようにクラッシュします。
java.lang.IllegalStateException: アダプターの内容が変更されましたが、ListView は通知を受け取りませんでした。アダプターのコンテンツがバックグラウンド スレッドからではなく、UI スレッドからのみ変更されていることを確認してください。[ListView(2131099654、class android.widget.ListView) with Adapter(class package.package.ArticleListAdapter)]
私のエラーは、アダプターを個別に作成したと思うにもかかわらず、アダプターが個別のインスタンスのように機能しないことが原因であると思います。私はこれについて助けを求めて周りを見回しましたが、私が見たほとんどは、別のアクティビティ内ではなく、バックグラウンド スレッドからデータを変更している人たちに関するものでした。
残念ながら、このコードは言い換えられています。一部は読みやすくするためであり、一部は別の人のために書いているためです。クローズド ソース ヤッダ ヤッダ...
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;
}
}
助けてくれてありがとう、私は本当に立ち往生しています。
また、Github の koush と Jwsonic の UrlImageViewer に関する作業に感謝し、感謝します。それは素晴らしいです。
編集:これが私の 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 のコードが実行されないようにしたことです。私が知る限り、それで問題は解決したようです。ご助力いただきありがとうございます!