How can I update a single row in a ListView?

前端 未结 11 1980
时光说笑
时光说笑 2020-11-22 17:07

I have a ListView which displays news items. They contain an image, a title and some text. The image is loaded in a separate thread (with a queue and all) and w

相关标签:
11条回答
  • 2020-11-22 17:40

    This is how I did it:

    Your items (rows) must have unique ids so you can update them later. Set the tag of every view when the list is getting the view from adapter. (You can also use key tag if the default tag is used somewhere else)

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        View view = super.getView(position, convertView, parent);
        view.setTag(getItemId(position));
        return view;
    }
    

    For the update check every element of list, if a view with given id is there it's visible so we perform the update.

    private void update(long id)
    {
    
        int c = list.getChildCount();
        for (int i = 0; i < c; i++)
        {
            View view = list.getChildAt(i);
            if ((Long)view.getTag() == id)
            {
                // update view
            }
        }
    }
    

    It's actually easier than other methods and better when you dealing with ids not positions! Also you must call update for items which get visible.

    0 讨论(0)
  • 2020-11-22 17:40

    In addition to this solution (https://stackoverflow.com/a/3727813/5218712) just want to add that it should work only if listView.getChildCount() == yourDataList.size(); There could be additional view inside ListView.

    Example of how the child elements are populated:

    0 讨论(0)
  • 2020-11-22 17:41

    exactly I used this

    private void updateSetTopState(int index) {
            View v = listview.getChildAt(index -
                    listview.getFirstVisiblePosition()+listview.getHeaderViewsCount());
    
            if(v == null)
                return;
    
            TextView aa = (TextView) v.findViewById(R.id.aa);
            aa.setVisibility(View.VISIBLE);
        }
    
    0 讨论(0)
  • 2020-11-22 17:45

    My solution: If it is correct*, update the data and viewable items without re-drawing the whole list. Else notifyDataSetChanged.

    Correct - oldData size == new data size, and old data IDs and their order == new data IDs and order

    How:

    /**
     * A View can only be used (visible) once. This class creates a map from int (position) to view, where the mapping
     * is one-to-one and on.
     * 
     */
        private static class UniqueValueSparseArray extends SparseArray<View> {
        private final HashMap<View,Integer> m_valueToKey = new HashMap<View,Integer>();
    
        @Override
        public void put(int key, View value) {
            final Integer previousKey = m_valueToKey.put(value,key);
            if(null != previousKey) {
                remove(previousKey);//re-mapping
            }
            super.put(key, value);
        }
    }
    
    @Override
    public void setData(final List<? extends DBObject> data) {
        // TODO Implement 'smarter' logic, for replacing just part of the data?
        if (data == m_data) return;
        List<? extends DBObject> oldData = m_data;
        m_data = null == data ? Collections.EMPTY_LIST : data;
        if (!updateExistingViews(oldData, data)) notifyDataSetChanged();
        else if (DEBUG) Log.d(TAG, "Updated without notifyDataSetChanged");
    }
    
    
    /**
     * See if we can update the data within existing layout, without re-drawing the list.
     * @param oldData
     * @param newData
     * @return
     */
    private boolean updateExistingViews(List<? extends DBObject> oldData, List<? extends DBObject> newData) {
        /**
         * Iterate over new data, compare to old. If IDs out of sync, stop and return false. Else - update visible
         * items.
         */
        final int oldDataSize = oldData.size();
        if (oldDataSize != newData.size()) return false;
        DBObject newObj;
    
        int nVisibleViews = m_visibleViews.size();
        if(nVisibleViews == 0) return false;
    
        for (int position = 0; nVisibleViews > 0 && position < oldDataSize; position++) {
            newObj = newData.get(position);
            if (oldData.get(position).getId() != newObj.getId()) return false;
            // iterate over visible objects and see if this ID is there.
            final View view = m_visibleViews.get(position);
            if (null != view) {
                // this position has a visible view, let's update it!
                bindView(position, view, false);
                nVisibleViews--;
            }
        }
    
        return true;
    }
    

    and of course:

    @Override
    public View getView(final int position, final View convertView, final ViewGroup parent) {
        final View result = createViewFromResource(position, convertView, parent);
        m_visibleViews.put(position, result);
    
        return result;
    }
    

    Ignore the last param to bindView (I use it to determine whether or not I need to recycle bitmaps for ImageDrawable).

    As mentioned above, the total number of 'visible' views is roughly the amount that fits on the screen (ignoring orientation changes etc), so no biggie memory-wise.

    0 讨论(0)
  • 2020-11-22 17:49
    int wantedPosition = 25; // Whatever position you're looking for
    int firstPosition = linearLayoutManager.findFirstVisibleItemPosition(); // This is the same as child #0
    int wantedChild = wantedPosition - firstPosition;
    
    if (wantedChild < 0 || wantedChild >= linearLayoutManager.getChildCount()) {
        Log.w(TAG, "Unable to get view for desired position, because it's not being displayed on screen.");
        return;
    }
    
    View wantedView = linearLayoutManager.getChildAt(wantedChild);
    mlayoutOver =(LinearLayout)wantedView.findViewById(R.id.layout_over);
    mlayoutPopup = (LinearLayout)wantedView.findViewById(R.id.layout_popup);
    
    mlayoutOver.setVisibility(View.INVISIBLE);
    mlayoutPopup.setVisibility(View.VISIBLE);
    

    For RecycleView please use this code

    0 讨论(0)
提交回复
热议问题