2012-04-05 3 views
10

notifyDatasetChanged()를 호출 할 때 listview가 업데이트되지 않는 이유는 무엇입니까? 유일한 방법은 내가 다시 ListView에에 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을 넣어 의미합니다. 다음

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

그러나 다시, 지금까지 내가 알고 있어요으로 그렇게 할 이유가 정말 없다 : 당신은 오히려 ArrayList과 루프 호출 후 ScoreItem의 저장, 한 번 어댑터를 업데이트하는 경우

.

+0

또한 루프에서 알림을 호출하려고했지만 아무 것도 변경하지 못했습니다. –

+0

UI 스레드에서 호출하지 않는 것 같습니다. 예를 들어 UI 스레드에서'.notifyDataSetChanged()'를 호출해야합니다. runOnuiThread를 사용하여 (새로운 Runnable() {...}); – Reinier

+0

도 변경되지 않습니다. –

1

사용자 지정 BaseAdapter 구현이 올바른지 확실하지 않습니다.

시도 나는 또한 BaseAdapter을 구현하는 방법에 도움이 될 수있는이 간단한 tutorial을 발견

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

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

에 변경. 이 문제가 발생하면 notifyDataSetChanged()를 다시 시도 할 수 있습니다.

+0

그게 도움이되지 않았다 –

+0

이것은 나를 위해 일한 것입니다. 약간의 연구를했는데 유효한 itemId를 제공하지 않으면 BaseAdapter에 DataSetObserver가 없을 것입니다.이 어댑터를 사용하지 않으면 어댑터에 데이터 변경 사항이 통지되지 않습니다. –

5

약간 늦었지만 대답은 당신이 난 그냥 그 두 가지 방법을 추가 한 후 작동을 멈출 사람, 의도 한대로 작동하는 간단한 BaseAdapter했다

public void registerDataSetObserver(DataSetObserver arg0) { 

} 

public void unregisterDataSetObserver(DataSetObserver arg0) { 

} 

구현하지 않아야합니다. 나는 누군가가 데이터 변경 등을 관찰 할 필요가 있다고 생각한다. :)

관련 문제