2013-06-30 69 views
1

我有一個ActivityListView附加到custom adapter如何刷新listView(帶適配器)後androidnd回調

我有一個回調,表示一個可繪製項目完成下載。

它被調用多次(每個資源被下載)。

在我的回調中,我切換到UI線程,並將一個新陣列設置到同一個適配器。

然後我打電話adapter.notifyDataSetChanged()

但活動列表不會刷新到新的圖標。

我還需要做什麼?

1)致電mListView.requestLayout()?但我怎麼知道什麼時候?

as notifyDataSetChanged是異步的,我不知道它什麼時候完成。

2)覆蓋adapter's destroyView?所以我不會創建一個新的listItem,但使用現有的?

我的適配器代碼:

公共類SettingValueAdapter延伸BaseAdapter {

private SettingsValue[] values; 
private LayoutInflater inflater; 
public SettingValueAdapter(Context context) { 
    inflater = LayoutInflater.from(context); 
} 

public SettingsValue[] getValues() { 
    return values; 
} 

@Override 
public int getCount() { 
    if (values == null) { 
     return 0; 
    } 
    return values.length; 
} 


@Override 
public Object getItem(int arg0) { 
    return values==null? null : values[arg0];  
} 

@Override 
public long getItemId(int arg0) { 
    // TODO Auto-generated method stub 
    return 0; 
} 

@Override 
public View getView(int position, View convertView, ViewGroup parent) { 
    if (convertView == null) { 
     convertView = inflater.inflate(R.layout.settings_item, null); 
    } 
    SettingsValue item = values[position]; 
    CheckedTextView name = (CheckedTextView) convertView.findViewById(R.id.itemText); 
    ImageView iconView = (ImageView) convertView.findViewById(R.id.itemIcon); 
    if (iconView != null && (item != null) && (item.icon != null)) { 
     iconView.setImageDrawable(item.icon); 
     iconView.setVisibility(View.VISIBLE); 
    } else { 
     iconView.setVisibility(View.GONE); 
    } 
    name.setText(item.display); 
    name.setChecked(item.isSelected); 
    View container = convertView.findViewById(R.id.itemContainer); 
    if (position == 0) { 
     if (position == values.length-1) { 
      container.setBackgroundResource(R.drawable.item_selector_single); 
     } else { 
      container.setBackgroundResource(R.drawable.item_selector_top); 
     } 
    } else { 
     if (position == values.length-1) { 
      container.setBackgroundResource(R.drawable.item_selector_bottom); 
     } else { 
      container.setBackgroundResource(R.drawable.item_selector_middle); 
     } 
    } 
    container.setPadding(0, 0, 0, 0); 
    return convertView; 
} 

public void setValues(SettingsValue[] values) { 
    this.values = values; 
    notifyDataSetChanged(); 
} 

}

MyActivity代碼:

public class CategoriesActivity extends ActivityBase { 
    private Category[] categories; 

    SettingValueAdapter adapter; 
    ListView   mListView; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.settings_values); 
     ((TitleBar) findViewById(R.id.theTitleBar)).init(this, 
       DisplayStrings.DS_CATEGORIES); 

     adapter = new SettingValueAdapter(this); 

     DriveToNativeManager nativeManager = DriveToNativeManager.getInstance(); 
     nativeManager.getCategories(new CategoriesListener() { 

      @Override 
      public void onComplete(Category[] aCategories) { 
       categories = aCategories; 

       NativeManager nativeManager = AppService.getNativeManager(); 
       SettingsValue[] values = new SettingsValue[categories.length]; 
       for (int i = 0; i < categories.length; i++) { 
        values[i] = new SettingsValue(
          categories[i].value, 
          nativeManager 
            .getLanguageString(categories[i].displayString), 
          false); 
        values[i].icon = ResManager 
          .GetSkinDrawable(categories[i].iconName + ".bin"); 
       } 
       adapter.setValues(values); 
      } 
     }); 
     mListView = (ListView) findViewById(R.id.settingsValueList); 
     mListView.setAdapter(adapter); 
     mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { 
      @Override 
      public void onItemClick(AdapterView<?> arg0, View arg1, 
        int position, long arg3) { 
       Intent intent = new Intent(CategoriesActivity.this, 
         SearchActivity.class); 
       intent.putExtra(PublicMacros.SEARCH_CATEGORY, 
         categories[position].value); 
       intent.putExtra(PublicMacros.SEARCH_MODE, 
         PublicMacros.FREE_SEARCH); 
       startActivityForResult(intent, 1); 
      } 
     }); 
    } 

    @Override 
    protected void onActivityResult(int requestCode, int resultCode, Intent data) { 

     if (resultCode == RESULT_OK) { 
      setResult(RESULT_OK); 
      finish(); 
     } 

     super.onActivityResult(requestCode, resultCode, data); 
    } 

    public void refreshListIcons() { 

//  if (categories != null) { 
//   NativeManager nativeManager = AppService.getNativeManager(); 
//   SettingsValue[] values = new SettingsValue[categories.length]; 
//   for (int i = 0; i < categories.length; i++) { 
//    values[i] = new SettingsValue(
//      categories[i].value, 
//      nativeManager 
//        .getLanguageString(categories[i].displayString), 
//      false); 
//    values[i].icon = ResManager 
//      .GetSkinDrawable(categories[i].iconName + ".bin"); 
//   } 
//   

      if (categories != null) { 

       SettingsValue[] values = adapter.getValues(); 
       for (int i = 0; i < values.length; i++) { 
        values[i].icon = ResManager 
          .GetSkinDrawable(categories[i].iconName + ".bin"); 
       } 


      adapter.setValues(values); 
     } 

    } 
} 

我打電話refreshIconsList從回調。

但是,正如我所說 - 列表不刷新運行時,但只有在現有和重新進入活動。

我已經試過這一點,但沒有幫助:

public void refreshListIcons() { 

//  if (categories != null) { 
//   NativeManager nativeManager = AppService.getNativeManager(); 
//   SettingsValue[] values = new SettingsValue[categories.length]; 
//   for (int i = 0; i < categories.length; i++) { 
//    values[i] = new SettingsValue(
//      categories[i].value, 
//      nativeManager 
//        .getLanguageString(categories[i].displayString), 
//      false); 
//    values[i].icon = ResManager 
//      .GetSkinDrawable(categories[i].iconName + ".bin"); 
//   } 
//   
     runOnUiThread(new Runnable() { 

     @Override 
     public void run() { 
      if (categories != null) { 

       SettingsValue[] values = adapter.getValues(); 
       for (int i = 0; i < values.length; i++) { 
        values[i].icon = ResManager 
          .GetSkinDrawable(categories[i].iconName + ".bin"); 
       } 

       adapter.setValues(values); 

       mListView.setAdapter(adapter); 
       adapter.notifyDataSetChanged(); 
      } 
     } 
     }); 
    } 
+0

'notifyDataSetChanged'應該足夠了。你可以顯示適配器代碼,是否有一個原因,你需要設置一個新的陣列,你不能只更新當前的? –

+0

@PatrickEvans感謝您的幫助。我添加了代碼 –

+0

請參閱http://stackoverflow.com/questions/7325437/how-to-add-item-to-listview-at-runtime,在那裏他除了'notifyAll'之外還添加了'setContentView'。爲什麼? –

回答

1

通常使用notifyDataSetChanged()會工作。既然你的值只是一個數組,你有一個特殊的原因,你爲什麼使用擴展BaseAdapter而不是ArrayAdapter(它提供addremoveclear函數爲底層數組)。我懷疑使用BaseAdapter不會以您想要的方式通知您。如果這不會最終爲您工作,請嘗試在設置新值後使用View上的invalidate()強制刷新子視圖。另外,如果您計劃在此列表中包含許多行以獲得速度,我會強烈建議您使用「視圖持有者模式」。

1

試試這個:

  • mListView.setAdapter(適配器);在你的onCreate()的活動中。
  • 公共無效refreshListIcons(){

    runOnUiThread(new Runnable() { 
    
    @Override 
    public void run() { 
        if (categories != null) { 
    
         SettingsValue[] values = adapter.getValues(); 
         for (int i = 0; i < values.length; i++) { 
          values[i].icon = ResManager 
            .GetSkinDrawable(categories[i].iconName + ".bin"); 
         } 
    
    
         adapter.addAll(values); // *** ADD THIS LINE*** 
        } 
    } 
    }); 
    

    }

問題是,當你setAdapter後的回調。 因此,您必須在調用之前初始化適配器並在回調後添加值

相關問題