programing

Android 목록 보기를 새로 고치는 방법은 무엇입니까?

closeapi 2023. 7. 15. 10:09
반응형

Android 목록 보기를 새로 고치는 방법은 무엇입니까?

고치는 » »ListView동적 데이터를 추가/삭제한 후?

방문하기Adapter해당 어댑터의 데이터를 수정한 후에는 개체를 사용할 수 있습니다.

를 거는 사항notifyDataSetChanged()Google I/O 비디오에서 볼 수 있습니다.

또한 다음을 사용할 수 있습니다.

myListView.invalidateViews();

모든 것을 무시해 주세요.invalidate(),invalidateViews(),requestLayout() 질문에 이 질문에 대한 답입니다.

올바른 방법(운 좋게도 정답으로 표시됨)은 어댑터를 호출하는 입니다.

문제 해결

전화하는 경우notifyDataSetChanged()모든 레이아웃 방법도 도움이 되지 않습니다.를 믿어주세요.ListView제대로 업데이트되었습니다.차이를 찾지 못하면 어댑터의 데이터 출처를 확인해야 합니다.

있는 이라면, 실제로 한 것입니다.notifyDataSetChanged().

다시 내 데이터를 ▁the▁if)▁calling합▁the▁to▁data▁call▁▁have▁method▁or▁with▁toation▁memory야조▁backendll'▁a를 호출해야 합니다.notifyDataSetChanged().

중요한 것은 이것입니다.notifyDataSetChanged데이터 집합이 변경된 경우에만 작동합니다.따라서 변화가 일어나지 않을 경우 이를 확인할 수 있습니다.필요한 경우 디버그합니다.

어레이 어댑터와 기본 어댑터 비교

기본 어댑터처럼 수집을 관리할 수 있는 어댑터로 작업하는 것이 더 효과적이라는 것을 알게 되었습니다.ArrayAdapter와 같은 일부 어댑터는 이미 자체 컬렉션을 관리하기 때문에 업데이트를 위한 적절한 컬렉션을 찾기가 어렵습니다.그것은 대부분의 경우에 단지 불필요한 추가적인 어려움일 뿐입니다.

UI 스레드

이것은 UI 스레드에서 호출해야 하는 것이 사실입니다.다른 답변에는 이를 달성하는 방법에 대한 예가 나와 있습니다.그러나 UI 스레드 외부에서 이 정보를 작업하는 경우에만 필요합니다.이는 서비스 또는 UI가 아닌 스레드에서 발생한 것입니다.간단한 경우 버튼 클릭 또는 다른 활동/분절을 통해 데이터를 업데이트합니다.여전히 UI 스레드 내에 있습니다.OnUiTrhead에서 실행되는 것을 항상 터뜨릴 필요는 없습니다.

빠른 예제 프로젝트

https://github.com/hanscappelle/so-2250770.git 에서 찾을 수 있습니다.Android Studio(그라들)에서 프로젝트를 복제하여 열기만 하면 됩니다.이 프로젝트에는 주 활동성 빌딩이 있습니다.ListView모든 랜덤 데이터를 포함합니다.이 목록은 수행 메뉴를 사용하여 새로 고칠 수 있습니다.

이 예제에 대해 생성한 어댑터 구현에서 ModelObject는 데이터 수집을 표시합니다.

public class MyListAdapter extends BaseAdapter {

    /**
     * this is our own collection of data, can be anything we 
     * want it to be as long as we get the abstract methods 
     * implemented using this data and work on this data 
     * (see getter) you should be fine
     */
    private List<ModelObject> mData;

    /**
     * our ctor for this adapter, we'll accept all the things 
     * we need here
     *
     * @param mData
     */
    public MyListAdapter(final Context context, final List<ModelObject> mData) {
        this.mData = mData;
        this.mContext = context;
    }

    public List<ModelObject> getData() {
        return mData;
    }

    // implement all abstract methods here
}

주 활동의 코드

public class MainActivity extends Activity {

    private MyListAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView list = (ListView) findViewById(R.id.list);

        // create some dummy data here
        List<ModelObject> objects = getRandomData();
        // and put it into an adapter for the list
        mAdapter = new MyListAdapter(this, objects);
        list.setAdapter(mAdapter);

        // mAdapter is available in the helper methods below and the 
        // data will be updated based on action menu interactions

        // you could also keep the reference to the android ListView 
        // object instead and use the {@link ListView#getAdapter()} 
        // method instead. However you would have to cast that adapter 
        // to your own instance every time
    }

    /**
     * helper to show what happens when all data is new
     */
    private void reloadAllData(){
        // get new modified random data
        List<ModelObject> objects = getRandomData();
        // update data in our adapter
        mAdapter.getData().clear();
        mAdapter.getData().addAll(objects);
        // fire the event
        mAdapter.notifyDataSetChanged();
    }

    /**
     * helper to show how only changing properties of data 
     * elements also works
     */
    private void scrambleChecked(){
        Random random = new Random();
        // update data in our adapter, iterate all objects and 
        // resetting the checked option
        for( ModelObject mo : mAdapter.getData()) {
            mo.setChecked(random.nextBoolean());
        }
        // fire the event
        mAdapter.notifyDataSetChanged();
    }
}

추가 정보

listViews의 기능에 대한 또 다른 좋은 게시물은 http://www.vogella.com/articles/AndroidListView/article.html 에서 찾을 수 있습니다.

원하는 경우 언제든지 실행 가능으로 호출:

runOnUiThread(run);

OnCreate()실행 가능한 스레드를 설정합니다.

run = new Runnable() {
    public void run() {
        //reload content
        arraylist.clear();
        arraylist.addAll(db.readAll());
        adapter.notifyDataSetChanged();
        listview.invalidateViews();
        listview.refreshDrawableState();
    }
};

목록 보기를 동적으로 새로 고치는 동안 문제가 발생했습니다.

어댑터에서 알림 DataSetChanged()를 호출합니다.

notifyDataSetChanged()를 호출하는 방법/시기에 대한 몇 가지 추가 세부 사항은 이 Google I/O 비디오에서 확인할 수 있습니다.

이 경우 notifyDataSetChanged()가 제대로 작동하지 않았습니다[다른 클래스에서 notifyDataSetChanged를 호출했습니다].실행 중인 활동(스레드)에서 ListView를 편집한 경우를 대비하여,크리스토퍼 덕분에 그 영상은 마지막 힌트를 주었습니다.

나의 두번째 수업에서 나는 사용했습니다.

Runnable run = new Runnable(){
     public void run(){
         contactsActivity.update();
     }
};
contactsActivity.runOnUiThread(run);

내 활동에서 업데이트()에 액세스합니다.이 업데이트는 다음을 포함합니다.

myAdapter.notifyDataSetChanged();

어댑터에 보기를 새로 고치라고 말합니다.제가 말할 수 있는 한 잘 작동했습니다.

SimpleCursorAdapter를 사용하는 경우 Cursor 개체에서 requery()를 호출해 보십시오.

아직 ListView Refresh가 만족스럽지 않다면 이 스니펫을 보시면 됩니다. 이것은 listView를 DB에서 로드하기 위한 것입니다. 실제로 해야 할 일은 단순히 ListView를 다시 로드하는 것입니다. CRUD 작업을 수행한 후에는 코드를 작성하는 것이 최선의 방법은 아니지만 원하는 대로 ListView를 새로 고칠 수 있습니다.

제게 도움이 됩니다. 더 나은 해결책을 찾는다면 공유해주세요...

.............CRUD 작업을 수행합니다.
...........DBAdapter.open();DBAdapter.insert_inter_SingleList();DB_results를 가져와서 목록에 내용으로 추가합니다.
ls2.setAdapter(새 ArrayAdapter(DynTabsample).이것.안드로이드의R.layout.simple_list_item_1, DBA 어댑터.DB_ListView);
DBAdapter.close();

이 게시물에서 사람들이 제안한 솔루션은 주로 장치의 Android 버전에 따라 작동하거나 작동하지 않습니다.예를 들어 AddAll 방법을 사용하려면 Android:minSdkVersion="10"을 Android 장치에 넣어야 합니다.

모든 장치에 대한 이 문제를 해결하기 위해 어댑터에서 자체 방법을 생성하고 추가 및 제거 방법 내부에서 사용하는 방법은 ArrayAdapter에서 문제 없이 데이터를 업데이트합니다.

My Code: 나만의 데이터 클래스 Race Result를 사용하여, 당신은 나만의 데이터 모델을 사용합니다.

결과 GpRowAdapter.java

public class ResultGpRowAdapter extends ArrayAdapter<RaceResult> {

    Context context;
    int resource;
    List<RaceResult> data=null;

        public ResultGpRowAdapter(Context context, int resource, List<RaceResult> objects)           {
        super(context, resource, objects);

        this.context = context;
        this.resource = resource;
        this.data = objects;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ........
        }

        //my own method to populate data           
        public void myAddAll(List<RaceResult> items) {

        for (RaceResult item:items){
            super.add(item);
        }
    }

결과Gp.java

public class ResultsGp extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {

    ...........
    ...........
    ListView list = (ListView)findViewById(R.id.resultsGpList); 

    ResultGpRowAdapter adapter = new ResultGpRowAdapter(this,  R.layout.activity_result_gp_row, new ArrayList<RaceResult>()); //Empty data

   list.setAdapter(adapter);

   .... 
   ....
   ....
   //LOAD a ArrayList<RaceResult> with data

   ArrayList<RaceResult> data = new ArrayList<RaceResult>();
   data.add(new RaceResult(....));
   data.add(new RaceResult(....));
   .......

   adapter.myAddAll(data); //Your list will be udpdated!!!

SQL 데이터베이스에서 정보를 변경한 후에는 목록 보기를 새로 고칠 수 없습니다(구체적으로 확장 가능한 목록 보기). 따라서 notifyDataSetChanged()가 도움이 되지 않으면 먼저 목록을 지우고 notifyDataSetChanged()를 호출한 후 다시 추가할 수 있습니다.예를들면

private List<List<SomeNewArray>> arrayList;
List<SomeNewArray> array1= getArrayList(...);
List<SomeNewArray> array2= getArrayList(...);
arrayList.clear();
arrayList.add(array1);
arrayList.add(array2);
notifyDataSetChanged();

그게 당신에게 이해가 되기를 바랍니다.

새로 고칠 때 스크롤 위치를 유지하고 다음을 수행할 수 있습니다.

if (mEventListView.getAdapter() == null) {
    EventLogAdapter eventLogAdapter = new EventLogAdapter(mContext, events);
    mEventListView.setAdapter(eventLogAdapter);
} else {
    ((EventLogAdapter)mEventListView.getAdapter()).refill(events);
}

public void refill(List<EventLog> events) {
    mEvents.clear();
    mEvents.addAll(events);
    notifyDataSetChanged();
}

자세한 내용은 Android ListView: 새로 고칠 때 스크롤 위치 유지를 참조하십시오.

그냥 사용하기myArrayList.remove(position);수신기 내부:

  myListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override public void onItemClick(AdapterView<?> parent, android.view.View view, int position, long id) {
           myArrayList.remove(position);
           myArrayAdapter.notifyDataSetChanged();
        }
    });

데이터를 부풀리는 해당 목록의 단일 개체를 사용해야 합니다.ListView▁if우▁then된▁is변경▁reference.notifyDataSetChanged()작동하지 않습니다.목록 보기에서 요소를 삭제할 때마다 사용 중인 목록에서도 요소를 삭제합니다. 배열 목록 <> 또는 다른 항목인지 여부를 확인한 후 호출합니다.notifyDataSetChanged()어댑터 클래스의 개체에 있습니다.

이제 어댑터에서 어떻게 관리했는지 확인해 보겠습니다. 아래를 참조하십시오.

public class CountryCodeListAdapter extends BaseAdapter implements OnItemClickListener{

private Context context;
private ArrayList<CountryDataObject> dObj;
private ViewHolder holder;
private Typeface itemFont;
private int selectedPosition=-1;
private ArrayList<CountryDataObject> completeList;

public CountryCodeListAdapter(Context context, ArrayList<CountryDataObject> dObj) {
    this.context = context;
    this.dObj=dObj;
    completeList=new  ArrayList<CountryDataObject>();
    completeList.addAll(dObj);
    itemFont=Typeface.createFromAsset(context.getAssets(), "CaviarDreams.ttf");
}

@Override
public int getCount() {
    return dObj.size();
}

@Override
public Object getItem(int position) {
    return dObj.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}
@Override
public View getView(int position, View view, ViewGroup parent) {
    if(view==null){
        holder = new ViewHolder();
        LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(R.layout.states_inflator_layout, null);
        holder.textView = ((TextView)view.findViewById(R.id.stateNameInflator));
        holder.checkImg=(ImageView)view.findViewById(R.id.checkBoxState);
        view.setTag(holder);
    }else{
        holder = (ViewHolder) view.getTag();
    }
    holder.textView.setText(dObj.get(position).getCountryName());
    holder.textView.setTypeface(itemFont);

    if(position==selectedPosition)
     {
         holder.checkImg.setImageResource(R.drawable.check);
     }
     else
     {
         holder.checkImg.setImageResource(R.drawable.uncheck);
     }
    return view;
}
private class ViewHolder{
    private TextView textView;
    private ImageView checkImg;
}

public void getFilter(String name) {
    dObj.clear();
    if(!name.equals("")){
    for (CountryDataObject item : completeList) {
        if(item.getCountryName().toLowerCase().startsWith(name.toLowerCase(),0)){
            dObj.add(item);
        }
    }
    }
    else {
        dObj.addAll(completeList);
    }
    selectedPosition=-1;
    notifyDataSetChanged();
    notifyDataSetInvalidated(); 
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
        long id) {
    Registration reg=(Registration)context;
    selectedPosition=position;
    reg.setSelectedCountryCode("+"+dObj.get(position).getCountryCode());
    notifyDataSetChanged();
}
}

어댑터에 목록을 전달했다고 가정합니다.
예:

list.getAdapter().notifyDataSetChanged()

목록을 업데이트합니다.

에는 목록보서데삭를후한전합걸어다니야를화로 전화해야 합니다.refreshDrawableState()다음은 예입니다.

final DatabaseHelper db = new DatabaseHelper (ActivityName.this);

db.open();

db.deleteContact(arg3);

mListView.refreshDrawableState();

db.close();

그리고.deleteContact.DatabaseHelper은 수은어느정처보것럼입다니일도업▁like▁looks▁will다것▁be니▁class입처럼 보일 것입니다.

public boolean deleteContact(long rowId) {

   return db.delete(TABLE_NAME, BaseColumns._ID + "=" + rowId, null) > 0;

}

SimpleAdapter 업데이트 작업을 위해 DataSetChanged()에게 알림을 받을 수 없었기 때문에, 대신 removeAllView()를 사용하여 부모 레이아웃에 연결된 모든 뷰를 제거한 다음 ListView를 추가하고 UI를 업데이트할 수 있도록 했습니다.

LinearLayout results = (LinearLayout)findViewById(R.id.results);
ListView lv = new ListView(this);
ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
SimpleAdapter adapter = new SimpleAdapter( this, list, R.layout.directory_row, 
                new String[] { "name", "dept" }, new int[] { R.id.name, R.id.dept } );

for (...) { 
    HashMap<String, String> map = new HashMap<String, String>();
    map.put("name", name);
    map.put("dept", dept);
    list.add(map);
}

lv.setAdapter(adapter);
results.removeAllViews();     
results.addView(lv);

SimpleCursorAdapter를 사용하는 동안 어댑터에서 changeCursor(새 커서)를 호출할 수 있습니다.

ListView(단일 TextView에)를 스캔한 BLE 장치의 MAC 주소로 채우고 싶을 때도 마찬가지였습니다.

제가 한 일은 다음과 같습니다.

public class Fragment01 extends android.support.v4.app.Fragment implements ...
{
    private ListView                listView;
    private ArrayAdapter<String>    arrayAdapter_string;

...

@Override
public void onActivityCreated(Bundle savedInstanceState)
{
    ...
    this.listView= (ListView) super.getActivity().findViewById(R.id.fragment01_listView);
    ...
    this.arrayAdapter_string= new ArrayAdapter<String>(super.getActivity(), R.layout.dispositivo_ble_item, R.id.fragment01_item_textView_titulo);
    this.listView.setAdapter(this.arrayAdapter_string);
}


@Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord)
{
    ...
    super.getActivity().runOnUiThread(new RefreshListView(device));
}


private class RefreshListView implements Runnable
{
    private BluetoothDevice bluetoothDevice;

    public RefreshListView(BluetoothDevice bluetoothDevice)
    {
        this.bluetoothDevice= bluetoothDevice;
    }

    @Override
    public void run()
    {
        Fragment01.this.arrayAdapter_string.add(new String(bluetoothDevice.toString()));
        Fragment01.this.arrayAdapter_string.notifyDataSetChanged();
    }
}

그런 다음 ListView가 발견된 장치의 MAC 주소로 동적으로 채워지기 시작했습니다.

리프레쉬가 무슨 뜻인지에 따라 다르다고 생각합니다.GUI 디스플레이를 새로 고쳐야 한다는 뜻입니까? 아니면 getChildAt(int)를 프로그래밍 방식으로 호출하여 어댑터에 있는 것에 해당하는 보기를 가져올 수 있도록 하위 보기를 새로 고쳐야 한다는 뜻입니까?

GUI 디스플레이를 새로 고치려면 어댑터에서 notifyDataSetChanged()를 호출합니다.다음에 다시 그릴 때 GUI가 새로 고쳐집니다.

getChildAt(int)를 호출하고 어댑터의 내용을 반영하는 보기를 얻으려면 layoutChildAt()를 호출합니다.그러면 어댑터 데이터에서 하위 보기가 재구성됩니다.

목록 보기에 표시할 배열 목록이 있습니다.배열 목록에 mysql의 요소가 포함되어 있습니다.Refresh 메서드를 재정의하고 해당 메서드에서 tablelayout.removeAllViews()를 사용한 다음 데이터베이스에서 데이터를 다시 가져오는 프로세스를 반복했습니다.그러나 그 전에 어레이 목록이나 데이터 구조 또는 새 데이터가 이전 데이터 구조에 추가될 것인지 확인하십시오.

서비스에서 UI 목록 보기를 업데이트하려면 기본 작업에서 어댑터를 정적으로 설정하고 다음 작업을 수행합니다.

@Override
public void onDestroy() {
    if (MainActivity.isInFront == true) {
        if (MainActivity.adapter != null) {
            MainActivity.adapter.notifyDataSetChanged();
        }

        MainActivity.listView.setAdapter(MainActivity.adapter);
    }
}    

ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅜㅜㅜㅜㅜContentProviders에서 Database을 그고당그표있습다니고시하에 .ListView 사용CursorLoader그리고.CursorAdapters그러면 관련 데이터의 모든 변경 내용이 목록 보기에 자동으로 반영됩니다.

당신의.getContext().getContentResolver().notifyChange(uri, null);에의 에.ContentProvider변화를 반영하기에 충분할 것입니다.추가 작업이 필요 없습니다.

그러나 이러한 기능을 모두 사용하지 않는 경우에는 데이터 세트가 변경되는 시점을 어댑터에 알려야 합니다. 집합 list 채우고 "" " " " " " " " " " " " " " " " " " " " " " " " ( " " " " " " 을 .notifyDataSetChanged()어댑터에 있습니다.

notifyDataSetChanged()데이터 집합에 변경 사항이 없으면 작동하지 않습니다.입니다.

/**
 * Notifies the attached observers that the underlying data has been changed
 * and any View reflecting the data set should refresh itself.
 */

새 어댑터 데이터를 가져온 다음 목록 보기에 맞게 어댑터를 재설정한 다음 다음과 같은 호출을 해야만 notifyDataSetChanged를 얻을 수 있었습니다.

    expandableAdapter = baseFragmentParent.setupEXLVAdapter();
    baseFragmentParent.setAdapter(expandableAdapter);
    expandableAdapter.notifyDataSetChanged(); 

은 " 다선사항은택른은"입니다.onWindowFocusChanged 추가 합니다. ㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅠㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜㅜ

 override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)

       // some controls needed
        programList = usersDBHelper.readProgram(model.title!!)
        notesAdapter = DailyAdapter(this, programList)
        notesAdapter.notifyDataSetChanged()
        listview_act_daily.adapter = notesAdapter
    }

여기서 제 시나리오에 대해 이야기를 했다면, 삭제 버튼과 함께 DB 값 목록을 보여주는 활동이 있었고 삭제 버튼을 눌렀을 때 해당 항목을 목록에서 삭제하고 싶었기 때문에 위의 답변 중 아무 것도 작동하지 않을 것입니다.

멋진 점은 재활용품 뷰를 사용하지 않고 단순한 목록 뷰와 어댑터 클래스에서 초기화된 목록 뷰를 사용했다는 것입니다.그래서, 전화를 하는 것.notifyDataSetChanged()delete 메서드가 어댑터 클래스에 있었기 때문에 어댑터 클래스 내부 및 어댑터 개체가 초기화된 활동 클래스에서도 작업을 수행하지 않습니다.

클래스의 이었습니다.getView하려면 을 합니다.)clear()).

내 코드가 어떻게 생겼는지 당신이 알기 위해서라면

public class WordAdapter extends ArrayAdapter<Word> {
  Context context;

  public WordAdapter(Activity context, ArrayList<Word> words) {}
    //.......

    @NonNull
    @Override
    public View getView(final int position, View convertView, ViewGroup group) {
      //.......
     ImageButton deleteBt = listItemView.findViewById(R.id.word_delete_bt);
     deleteBt.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
             if (vocabDb.deleteWord(currentWord.id)) {
                //.....
             } else{
                //.....
             }
             remove(getItem(position)); // <---- here is the trick ---<
             //clear() // if you want to clear everything
         }
    });
 //....

: 여기remove()그리고.getItem()메서드는 어댑터 클래스에서 상속됩니다.

  • remove()한 합니다.
  • getItem(position)클릭한 위치에서 항목(여기서 목록에 추가한 내 Word 개체)을 가져오는 것입니다.

이렇게 활동 클래스의 목록 보기에 어댑터를 설정했습니다.

    ArrayList<Word> wordList = new ArrayList();
    WordAdapter adapter = new WordAdapter(this, wordList);

    ListView list_view = (ListView) findViewById(R.id.activity_view_words);
    list_view.setAdapter(adapter);

"dataArray"에서 동적 데이터를 추가/삭제한 후 다음 작업을 수행합니다.

어레이 어댑터를 사용하는 경우
adapter.notifyDataSetChanged();
어레이 어댑터를 확장하는 사용자 정의 어댑터를 사용하는 경우
adapter.clear();
adapter.addAll(dataArray);
adapter.notifyDataSetChanged();
기본 어댑터를 확장하는 사용자 지정 어댑터를 사용하는 경우
adapter.clear();
adapter.getData().addAll(dataArray);
adapter.getData().notifyDataSetChanged();

가장 쉬운 방법은 새 Adaper를 만들고 이전 Adaper를 삭제하는 것입니다.

myListView.setAdapter(new MyListAdapter(...));

언급URL : https://stackoverflow.com/questions/2250770/how-to-refresh-android-listview

반응형