2012-04-05 18 views
10

notifyDatasetChanged()を呼び出すと、リストビューが更新されないのはなぜですか? 唯一の方法は、私はそれが再びリストビューにsetAdatper()を呼び出すために、データは表示させることができます...私はまたBaseAdapter.notifyDatasetChanged()がListViewを更新しない

何もアダプタを変更しなかったrunOnUIThread()を経由して、それを呼び出そうとしました

/** 
* Adapter to provide the data for the online scores 
* 
* @author soh#zolex 
* 
*/ 
public class OnlineScoresAdapter extends BaseAdapter { 

    private Context context; 
    private List<ScoreItem> scores = new ArrayList<ScoreItem>(); 

    /** 
    * Constructor 
    * 
    * @param Context context 
    */ 
    public OnlineScoresAdapter(Context context) { 

     this.context = context; 
    } 

    /** 
    * Add an item to the adapter 
    * 
    * @param item 
    */ 
    public void addItem(ScoreItem item) { 

     this.scores.add(item); 
    } 

    /** 
    * Get the number of scores 
    * 
    * @return int 
    */ 
    public int getCount() { 

     return this.scores.size(); 
    } 

    /** 
    * Get a score item 
    * 
    * @param int pos 
    * @return Object 
    */ 
    public Object getItem(int pos) { 

     return this.scores.get(pos); 
    } 

    /** 
    * Get the id of a score 
    * 
    * @param in pos 
    * @retrn long 
    */ 
    public long getItemId(int pos) { 

     return 0; 
    } 

    /** 
    * Get the type of an item view 
    * 
    * @param int pos 
    * @return int 
    */ 
    public int getItemViewType(int arg0) { 

     return arg0; 
    } 

    /** 
    * Create the view for a single list item. 
    * Load it from an xml layout. 
    * 
    * @param int pos 
    * @param View view 
    * @param ViewGroup viewGroup 
    * @return View 
    */ 
    public View getView(int pos, View view, ViewGroup group) { 

     LinearLayout layout; 
     if (view == null) { 

      layout = (LinearLayout)View.inflate(this.context, R.layout.scoreitem, null); 

     } else { 

      layout = (LinearLayout)view; 
     } 

     TextView position = (TextView)layout.findViewById(R.id.pos); 
     TextView time = (TextView)layout.findViewById(R.id.time); 
     TextView player = (TextView)layout.findViewById(R.id.player); 
     TextView createdAt = (TextView)layout.findViewById(R.id.created_at); 

     ScoreItem item = (ScoreItem)getItem(pos); 
     player.setText(item.player); 
     position.setText(String.valueOf(new Integer(item.position)) + "."); 
     time.setText(String.format("%.4f", item.time)); 
     createdAt.setText(item.created_at); 

     return layout; 
    } 

    /** 
    * Get the number of different views 
    * 
    * @return int 
    */ 
    public int getViewTypeCount() { 

     return 1; 
    } 

    /** 
    * Return wheather the items have stable IDs or not 
    * 
    * @return boolean 
    */ 
    public boolean hasStableIds() { 

     return false; 
    } 

    /** 
    * Return wheather the list is empty or not 
    * 
    * @return boolean 
    */ 
    public boolean isEmpty() { 

     return this.scores.size() == 0; 
    } 

    /** 
    * No need of a data observer 
    * 
    * @param DataSetObserver arg0 
    * @return void 
    */ 
    public void registerDataSetObserver(DataSetObserver arg0) { 

    } 

    /** 
    * No need of a data observer 
    * 
    * @param DataSetObserver arg0 
    * @return void 
    */ 
    public void unregisterDataSetObserver(DataSetObserver arg0) { 

    } 

    /** 
    * No item should be selectable 
    * 
    * @return boolean 
    */ 
    public boolean areAllItemsEnabled() { 

     return false; 
    } 

    /** 
    * No item should be selectable 
    * 
    * @param int pos 
    * @return boolean 
    */ 
    public boolean isEnabled(int arg0) { 

     return false; 
    } 
} 

活動

XMLLoaderThreadが正常に動作し、それだけでnotifyDatasetChangedは何もしないように思われます...

/** 
* Obtain and display the online scores 
* 
* @author soh#zolex 
* 
*/ 
public class OnlineScoresDetails extends ListActivity { 

    WakeLock wakeLock; 
    OnlineScoresAdapter adapter; 
    boolean isLoading = false; 
    int chunkLimit = 50; 
    int chunkOffset = 0; 

    @Override 
    /** 
    * Load the scores and initialize the pager and adapter 
    * 
    * @param Bundle savedInstanceState 
    */ 
    public void onCreate(Bundle savedInstanceState) { 

     super.onCreate(savedInstanceState); 

     PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 
     this.wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "racesow"); 

     adapter = new OnlineScoresAdapter(this); 
     setListAdapter(adapter); 
     this.loadData(); 

     setContentView(R.layout.listview); 
     getListView().setOnScrollListener(new OnScrollListener() { 

      public void onScrollStateChanged(AbsListView view, int scrollState) { 

      } 

      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 

       if (totalItemCount > 0 && visibleItemCount > 0 && firstVisibleItem + visibleItemCount >= totalItemCount) { 

        if (!isLoading) { 

         loadData(); 
        } 
       } 
      } 
     }); 
    } 

    public void loadData() { 

     final ProgressDialog pd = new ProgressDialog(OnlineScoresDetails.this); 
     pd.setProgressStyle(ProgressDialog.STYLE_SPINNER); 
     pd.setMessage("Obtaining scores..."); 
     pd.setCancelable(false); 
     pd.show(); 

     isLoading = true; 
     String mapName = getIntent().getStringExtra("map"); 
     XMLLoaderThread t = new XMLLoaderThread("http://racesow2d.warsow-race.net/map_positions.php?name=" + mapName + "&offset=" + this.chunkOffset + "&limit=" + this.chunkLimit, new Handler() { 

      @Override 
      public void handleMessage(Message msg) { 

       switch (msg.what) { 

        // network error 
        case 0: 
         new AlertDialog.Builder(OnlineScoresDetails.this) 
          .setMessage("Could not obtain the maplist.\nCheck your network connection and try again.") 
          .setNeutralButton("OK", new OnClickListener() { 

           public void onClick(DialogInterface arg0, int arg1) { 

            finish(); 
            overridePendingTransition(0, 0); 
           } 
          }) 
          .show(); 
         break; 

        // maplist received 
        case 1: 
         pd.dismiss(); 
         InputStream xmlStream; 
         try { 

          xmlStream = new ByteArrayInputStream(msg.getData().getString("xml").getBytes("UTF-8")); 
          XMLParser parser = new XMLParser(); 
          parser.read(xmlStream); 

          NodeList positions = parser.doc.getElementsByTagName("position"); 
          int numPositions = positions.getLength(); 
          for (int i = 0; i < numPositions; i++) { 

           Element position = (Element)positions.item(i); 

           ScoreItem score = new ScoreItem(); 
           score.position = Integer.parseInt(parser.getValue(position, "no")); 
           score.player = parser.getValue(position, "player"); 
           score.time = Float.parseFloat(parser.getValue(position, "time")); 
           score.created_at = parser.getValue(position, "created_at"); 

           adapter.addItem(score); 
          } 

          adapter.notifyDataSetChanged(); 


          chunkOffset += chunkLimit; 
          isLoading = false; 

         } catch (UnsupportedEncodingException e) { 

          new AlertDialog.Builder(OnlineScoresDetails.this) 
           .setMessage("Internal error: " + e.getMessage()) 
           .setNeutralButton("OK", null) 
           .show(); 
         } 

         break; 
       } 

       pd.dismiss(); 
      } 
     }); 

     t.start(); 
    } 

    /** 
    * Acquire the wakelock on resume 
    */ 
    public void onResume() { 

     super.onResume(); 
     this.wakeLock.acquire(); 
    } 

    /** 
    * Release the wakelock when leaving the activity 
    */ 
    public void onDestroy() { 

     super.onDestroy(); 
     this.wakeLock.release(); 
    } 

    /** 
    * Disable animations when leaving the activity 
    */ 
    public void onBackPressed() { 

     this.finish(); 
     this.overridePendingTransition(0, 0); 
    } 
} 
+0

エラーメッセージが表示されますか?また、forループの前にnumPositionsの値をチェックしましたか? –

+0

私が言ったように、notifiyDataSetChanged()の代わりにsetListAdapter()を呼び出すと、データが表示されますが、リストはユーザがスクロールした場所ではなく先頭から始まります。データはそこにありますが、ビューは更新されません –

+0

また、AsyncTaskでこれを試しました。同じ結果、ビューの更新はなく、setAdapter()を再度呼び出す場合に限ります。 –

答えて

0

データセットを操作するたびにadapter.notifyDataSetChanged()に電話する必要があります。

for(int i = 0; i < numPositions; i++) { 
    .... 
    adapter.addItem(score); 
    adapter.notifyDataSetChanged(); 
} 

は、あなたのUIスレッドからadapter.notifyDataSetChanged()を呼び出していることを確認してください:あなたはバッチ(例えばfor -loop)に項目を追加する場合、これはあなたがそうのように、あなたのループで.notifyDataSetChangedを配置する必要がありますを意味します。

するのではなく、一度あなたのアダプタを更新ArrayListで、ループ・コールの後、あなたのScoreItem秒保存する場合:その後、

adapter.addAll(scoreList); 
adapter.notifyDataSetChanged(); 

をしかし、再び、私の知る限り承知しているとしてそれをする理由は本当にありません。

+0

私はループ内でnotifyを呼び出そうとしましたが、何も変更しませんでした。 –

+0

UIスレッドから呼び出されていないようです。例えば、UIスレッドから '.notifyDataSetChanged()'を呼び出すようにしてください。 runOnuiThread(new Runnable(){...を使用して)}); – Reinier

+0

でも何も変わっていません –

1

カスタムBaseAdapterの実装が正しいかどうかはわかりません。

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

public long getItemId(int pos) { 
    return 0; 
} 

を変更してみてください私はまたBaseAdapterの実装方法の役に立つかもしれません。このシンプルなtutorialを見つけました。これを取得した後、notifyDataSetChanged()をもう一度試してみることができます。

+0

これは役に立たなかった –

+0

これは私のために働いたものです。私は少しの研究を行いましたが、有効なitemIdを指定しないと、BaseAdapterにはDataSetObserverがありませんでしたが、アダプタにはデータの変更が通知されません。 –

5
少し遅く

が、答えはあなたがそれらの2つのメソッドを追加した後に動作を停止することを目的として、私はちょうど働いてシンプルBaseAdapterを持っていた

public void registerDataSetObserver(DataSetObserver arg0) { 

} 

public void unregisterDataSetObserver(DataSetObserver arg0) { 

} 

を実装するべきではないです。私は、誰かがデータの変更などを観察する必要があることを想起します:)

関連する問題