【问题标题】:ListItems doubles in number(duplicated) in Custom ListView in android在 android 的自定义 ListView 中,ListItems 的数量翻倍(重复)
【发布时间】:2016-05-28 07:22:08
【问题描述】:

我正在使用自定义ListView,当我转到上一个活动并再次转到该 ListViewActivity 时,它的数量会翻倍(重复的 listItems)。

我可以看到问题发生在哪里。当我第一次进入 ListViewActivity 时,将列表项添加到 ArrayList 并设置适配器时,一切都很好。但是当我去上一个活动并再次进入 ListViewActivity 时,先前设置的列表项仍然存在于 Adapter 中,并且当进程通过 setAdapter() 时再次设置列表项,这导致了列表项的重复。

我遇到过许多解决方案,例如使用notifyDataSetChanged()、清除ArrayListsetAdapter(null) 等。这些解决方案都没有帮助我。

我想解决方案是清除 AdapterArrayList 并刷新 Adapter。但我不知道具体怎么做以及在哪里做。

这是我的代码:

这是LoadingActivity.java中的数据接收类

private class CategoriesAsyncTask extends AsyncTask<String,Integer,Double>{

     String res="";
     String curState ="";
     String httppoststr="";
     boolean isNxtActivity=false;

     @Override
    protected Double doInBackground(String... params) {
        // TODO Auto-generated method stub

        postData(params[0]);
        return null;

     }
     protected void onPostExecute(Double Result)
     {  
        if(isNxtActivity)
        {   
            Intent intent = new Intent(LoadingActivity.this, ListItemsActivity.class);
            if(curState.equals(Constants.STATE_GET_STOCK_ITEMS))
            {
                intent.putStringArrayListExtra(Constants.STOCK_ITEMS_LIST, listOfItems);
                intent.putExtra("curState", Constants.STATE_GET_STOCK_ITEMS);
                intent.putExtra(Constants.CATEGORY_ID, categoryId);
                intent.putExtra(Constants.CUSTOMER_ID, customerId);
                LoadingActivity.this.startActivity(intent);
            }
        }
    }

    public void postData(String ValueIWantToSend) {
        // Create a new HttpClient and Post Header
        HttpClient httpclient = new DefaultHttpClient();
        HttpPost httppost = new HttpPost(Constants.GatewayUrl);
        try
        {
            JSONObject json = new JSONObject(ValueIWantToSend);
            curState = json.getString("curState");
            StringEntity se = new StringEntity(ValueIWantToSend);
            httppost.setEntity(se);
            httppost.setHeader("Accept", "application/json");
            httppost.setHeader("Content-type", "application/json");
            httppoststr =httppost.toString();
            // Execute HTTP Post Request
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            res = EntityUtils.toString(entity, "UTF-8");
            JSONObject jsonobj = new JSONObject(res);
            String state = jsonobj.getString(Constants.STATE);

            if(Constants.RESPONSE_SUCCESS.equals(state.toLowerCase()))
            {
                isNxtActivity =true;
                if(curState.equals(Constants.STATE_GET_STOCK_ITEMS))
                {
                    JSONArray itemsListJsonArray=new JSONArray(); 
                    itemsListJsonArray=jsonobj.getJSONArray(Constants.STOCK_ITEMS_LIST);

                    for(int i=0;i<itemsListJsonArray.length();i++)
                    {
                        String itemslist=itemsListJsonArray.getString(i);
                        listOfItems.add(itemslist.toString());
                    }
                }
            }
        }
         catch (ClientProtocolException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            catch (JSONException e) {
                e.printStackTrace();
            }
    }
}

ListViewActivity.java

private String[] arrayOfNames;
private String[] arrayOfImageUrls;

ArrayList<String> listOfNames = new ArrayList<String>();
ArrayList<String> listOfImageUrls = new ArrayList<String>();

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

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

    Bundle extras = getIntent().getExtras();
    listOfItems = extras.getStringArrayList(Constants.STOCK_ITEMS_LIST); //The duplication occurs here while getting the data from the LoadingActivity when visiting this activity for the second time.

    arrayOfNames = new String[listOfNames.size()];
    for(int i=0;i<listOfNames.size();i++)
    {
        arrayOfNames[i]=listOfNames.get(i);
    }

    arrayOfImageUrls = new String[listOfImageUrls.size()];
    for(int i=0;i<listOfImageUrls.size();i++)
    {
        arrayOfImageUrls[i]=listOfImageUrls.get(i);
    } 

    listItemadapter = new CustomListItemsAdapter(this, arrayOfNames, arrayOfImageUrls); 
    itemsList.setAdapter(listItemadapter);
}

CustomAdapter.java

public class CustomListItemsAdapter extends BaseAdapter{

private Context context;
private LayoutInflater inflater;
private String[] arrayOfNames;

public CustomListItemsAdapter(ListItemsActivity listItemsActivity, String[] itemsName) {
    // TODO Auto-generated constructor stub

    context=listItemsActivity;
    arrayOfNames = itemsName;

    inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return arrayOfNames.length;
}

@Override
public Object getItem(int position) {
    // TODO Auto-generated method stub
    return position;
}

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

public static class ViewHolder
{
   private TextView itemName;
   private ImageView itemImage;
}

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

    ViewHolder holder;     

    if(convertView==null)
    {
        holder=new ViewHolder();
        convertView = inflater.inflate(R.layout.list_item_content, parent, false);

        holder.itemName = (TextView) convertView.findViewById(R.id.itemName);
        holder.itemImage = (ImageView) convertView.findViewById(R.id.itemImage);       

        convertView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.itemName.setText(arrayOfNames[position]);
    StrictMode.ThreadPolicy policy = new
            StrictMode.ThreadPolicy.Builder()
            .permitAll().build();
            StrictMode.setThreadPolicy(policy);

    ListItemsAsyncTask listAsync = new ListItemsAsyncTask();
    Drawable drawableIcon = listAsync.loadImageFromServer(arrayOfImageUrls[position]);
    holder.itemImage.setImageDrawable(drawableIcon);

 return convertView;
}

private class ListItemsAsyncTask extends AsyncTask<String, Integer, Double> {

    String httpPostStr, res;
    Boolean NextActivity = false;

    public Drawable loadImageFromServer(String url) 
    {
       try {
          InputStream is = (InputStream) new URL(url).getContent();
          Drawable drawable = Drawable.createFromStream(is, "src name");
          return drawable;
       } catch (Exception e) {
          e.printStackTrace(); 
          return null;
       }
    }

    @Override
    protected Double doInBackground(String... params) {
        return null;
    }
}

有什么建议吗???

更新:我发现了这个重复背后的问题。当我第二次来到 ListViewActivity 时,重复发生在 Bundle 中,我从中获取了 ListView 及其内容的数据。

现在我需要一个解决方案来阻止 Bundle 中的重复。我在 ListViewActivity.java 中用注释提到了重复发生的行

【问题讨论】:

  • 请向我们展示您的代码
  • @Nisarg 我已经添加了代码。

标签: android listview arraylist


【解决方案1】:

在onCreate()中只调用一次setAdapter()函数,因为onCreate()只在activity第一次启动时调用,第二次在activity启动时不调用onCreate(),但如果您销毁活动,则将再次调用 onCreate(),确保您没有销毁活动。

【讨论】:

  • 根据您的建议,我已经在onCreate() 中设置了一次 setAdapter() 并且我没有破坏任何东西。你确定只有在活动第一次启动时才调用 onCreate() 而我第二次启动活动时才调用 onCreate() 吗?
  • 是的 oncreate() 只被调用一次,随后的方法 onstart() 和 onresume() 被调用,然后在你第二次访问活动之后,发布 onresume() 代码 ....跨度>
  • ` @Override protected void onResume() { super.onResume(); listOfItems.clear(); listItemadapter.notifyDataSetChanged(); } `
【解决方案2】:

您可能正在onResume 中加载列表,并且您正在将项目添加到附加到适配器的列表中,并且每次都有重复项。

正确的方法是: 在onResume 中加载数据,确保您没有将重复项添加到列表中,或者在添加数据之前清除列表。然后在填充列表之后 - 检查适配器是否已初始化并附加如果已经初始化然后将数据添加到列表并在适配器 .notifyDataSetChanged() 上进行简单制作,如果未初始化,则通过将列表附加到它来初始化它。

请注意,当您将列表附加到适配器时,您将无法更改指向您的列表变量的指针:

yourList = downloadedList; // Wrong way you will override the pointer to list in adapter

必须是这样的:

yourList.clear();
yourList.addAll(downloadedList); // Correct way
adapter.notifyDataSetChanged();

【讨论】:

  • 您确定此代码应该在onResume() 中吗?因为每当我去 ListViewActivity onCreate() 时,只会在我在调试时发现它的地方调用。
  • onCreate() 在您创建活动时调用,onResume() 在每次活动变为活动时(前台)工作。如果您不需要在每次活动激活时重新加载数据,那么您可以将其移动到 onCreate() 并确保您在异步任务中下载数据,因为您将在数据更新时遇到 UI 卡住
  • 我在onResume() 中完成了您建议的代码,但没有任何更改。第二次去那个活动时,列表项仍然重复。
  • 如何将数据获取到“listOfNames”?此外,我看到错误使用异步任务
  • listOfNames 的数据从服务器接收并通过 LoadingActivity 传递给此 ListViewActivity。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-07
  • 2013-03-10
相关资源
最近更新 更多