【问题标题】:Duplicate item custom listview with BaseAdapter使用 BaseAdapter 重复项自定义列表视图
【发布时间】:2014-07-17 12:21:29
【问题描述】:

我尝试使用自定义 ListView 扩展 BaseAdapter 将数据从数据库 mysql 显示到列表视图。数据库中的数据如:

tbl_userbook:

    id   | username  |  title          | category
   ------+-----------+-----------------+-------------
    1    | A         |  Java           | 1
    2    | B         |  VB.NET         | 1
    3    | C         |  Swing Java     | 1
    4    | D         |  Java Hibernate | 1
    5    | E         |  C#             | 1
    6    | F         |  Ruby           | 1
    7    | G         |  MySQL          | 1
    8    | H         |  Sqlite         | 1
    9    | I         |  PHP            | 1
    10   | J         |  MsSQL          | 1

我的问题是为什么 listview 显示从 id 1 到 6 的重复项和数据 id 7、8、9、10 未显示在 listview 中。

Listview 中显示的数据如下:

    | username  |  title          | 
    +-----------+-----------------+
    | A         |  Java           |
    | B         |  VB.NET         |
    | C         |  Swing Java     |
    | D         |  Java Hibernate |
    | E         |  C#             |
    | F         |  Ruby           |
    | A         |  Java           | < ----  duplicate starting from here
    | B         |  VB.NET         |
    | C         |  Swing Java     |
    | D         |  Java Hibernate |

基础适配器:

public class HomeListViewAdapter extends BaseAdapter {

Context context;
ArrayList<HashMap<String, String>> userList;
HashMap<String, String> map = new HashMap<String, String>();

public HomeListViewAdapter(Context context,
        ArrayList<HashMap<String, String>> arraylist) {
    this.context = context;
    userList = arraylist;
}

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

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

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub

    TextView tvUsername, tvTitle;

    if (convertView == null) {
        LayoutInflater layoutInflator = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        convertView = layoutInflator.inflate(R.layout.custom_listview_home, parent, false);

        map = membersList.get(position);

        tvUsername = (TextView) convertView.findViewById(R.id.tvUsername);
        tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);

        tvUsername.setText(map.get(FragmentHome.USERNAME));
        tvTitle.setText(map.get(FragmentHome.TITLE));

    }
    return convertView;

片段

public class FragmentHome extends SherlockFragment {

public static String USERNAME = "username";
public static String TITLE = "title";

private ProgressDialog pDialog; 
JSONPostGet jPostget = new JSONPostGet();
JSONArray users = null;
ArrayList<HashMap<String, String>> userList;

private static String url_getbook = "http://....../get_userbook.php";

ListView list;
HomeListViewAdapter homeadapter;

private static final String KEY_SUCCESS = "success";
private static final String KEY_USERS = "users";
private static final String KEY_USERNAME = "username";
private static final String KEY_TITLE = "title";

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_home, container, false);
    userList = new ArrayList<HashMap<String,String>>();
    new LoadUserBook().execute();
    return rootView;
}

class LoadUserBook extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        pDialog = new ProgressDialog(getActivity());
        pDialog.setMessage("Please wait....");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    @Override
    protected String doInBackground(String... args) {
        // TODO Auto-generated method stub
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("category", "1"));
        JSONObject json = jPostget.makeHttpRequest(url_getbook, "GET", params);
        Log.d("All News Feed: ", json.toString());
        try {
            int success = json.getInt(KEY_SUCCESS);
            if (success == 1) {
                users = json.getJSONArray(KEY_USERS);
                for (int i = 0; i < users.length(); i++) {
                    JSONObject c = users.getJSONObject(i);

                    String suname = c.getString(KEY_USERNAME);
                    String stitle = c.getString(KEY_TITLE);

                    HashMap<String, String> map = new HashMap<String, String>();
                    map.put(KEY_USERNAME, suname);
                    map.put(KEY_TITLE, stitle);

                    userList.add(map);
                }
            } else {
                // ...
            }
        } catch (JSONException e) {
            // TODO: handle exception
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        pDialog.dismiss();
        try {
            getActivity().runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub      
                    list = (ListView) getView().findViewById(R.id.listview1);
                    homeadapter = new HomeListViewAdapter(getActivity(), userList);
                    list.setAdapter(homeadapter);
                    homeadapter.notifyDataSetChanged();
                }
            });
        } catch (Exception e) {
            // TODO: handle exception
        }
    }
}

}

请帮忙。感谢提前

【问题讨论】:

  • 在 doInBackground() 方法中使用 userList.clear() ,例如 . @Override protected String doInBackground(String... args) { userList.clear()
  • 哈哈。我只是删除它“ if (convertView == null) ”问题解决了,但请你给我一个为什么会发生这种情况的原因。
  • 你不应该删除它..它有助于保持顺利
  • 如果在 doInBackground() 中使用,我必须将代码“userList.clear()”放在哪里,数据不显示?
  • @eric : 那我该怎么办?

标签: android mysql listview android-listview baseadapter


【解决方案1】:

您的getView 实现不正确。试试这个 -

  @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub

        TextView tvUsername, tvTitle;

        if (convertView == null) {
            LayoutInflater layoutInflator = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            convertView = layoutInflator.inflate(R.layout.custom_listview_home, parent, false);   
        }


            map = membersList.get(position);

            tvUsername = (TextView) convertView.findViewById(R.id.tvUsername);
            tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);

            tvUsername.setText(map.get(FragmentHome.USERNAME));
            tvTitle.setText(map.get(FragmentHome.TITLE));

        return convertView;
}

【讨论】:

  • @Kshitij : 谢谢你,我用你的建议..我的问题解决了
【解决方案2】:

我认为您没有将 else 添加到为 convertView 指定的条件为 null。

所以现在你的代码只是为那些当前显示的视图设置数据,对于剩余的数据它重复之前已经初始化的视图。

就这样试试吧,我相信你会得到解决方案的:

if(convertView == null){
// some code here 
} 
else{
     holder = (ViewHolder) row.getTag();
}

【讨论】:

  • 谢谢你的解释,现在我明白了。
【解决方案3】:

我认为 getItem() 应该返回 userlist.get(position) 并在 onCreateView
地图 = membersList.get(位置);
应该是
ap = userlist.get(位置);

另一件事是当转换视图不为空时缺少 else 子句。

【讨论】:

    【解决方案4】:

    试试这个:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
    
        TextView tvUsername, tvTitle;
    
        if (convertView == null) {
            LayoutInflater layoutInflator = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    
            convertView = layoutInflator.inflate(R.layout.custom_listview_home, parent, false);
    
    
    
    
        }else{
           LayoutInflater layoutInflator = convertView;
    
        }
    
         map = membersList.get(position);
    
            tvUsername = (TextView) convertView.findViewById(R.id.tvUsername);
            tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);
    
            tvUsername.setText(map.get(FragmentHome.USERNAME));
            tvTitle.setText(map.get(FragmentHome.TITLE));
    
        return convertView;
    }
    

    【讨论】:

      【解决方案5】:

      解决方案:-

      您没有正确实现 Base 适配器。 android出于性能原因回收视图,因此您需要初始化文本图像等。每次。所以你只需要将初始化代码放在 convertview 空检查之外。 只需这样做:--

      @Override
      public View getView(int position, View convertView, ViewGroup parent) {
      // TODO Auto-generated method stub
      
      TextView tvUsername, tvTitle;
      
      if (convertView == null) {
          LayoutInflater layoutInflator = (LayoutInflater) context
                  .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      
          convertView = layoutInflator.inflate(R.layout.custom_listview_home, parent, false);
      
      
      
          tvUsername = (TextView) convertView.findViewById(R.id.tvUsername);
          tvTitle = (TextView) convertView.findViewById(R.id.tvTitle);
      
      
      
      }
      map = membersList.get(position);
      tvUsername.setText(map.get(FragmentHome.USERNAME));
          tvTitle.setText(map.get(FragmentHome.TITLE));
      return convertView;
      }
      

      【讨论】:

        【解决方案6】:

        public View getView(int position, View view, ViewGroup parent) { // TODO 自动生成的方法存根

                    // get the layout inflater
        
                    LayoutInflater mLayoutInflater = (LayoutInflater) getApplicationContext()
                            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        
                    // create a ViewHolder reference
                    ViewHolder holder = null;
        
                    // check to see if the reused view is null or not, if is not
                    // null then reuse it
        
                    if (view == null) {
                        holder = new ViewHolder();
                        // check to see if the reused view is null or not, if is not
                        // null then reuse it
                        if (view == null) {
                            holder = new ViewHolder();
        
                            view = mLayoutInflater.inflate(
                                    R.layout.listview_values, null);
                            holder.txt_date = (TextView) view
                                    .findViewById(R.id.t_date);
                            holder.txt_intime = (TextView) view
                                    .findViewById(R.id.txt_intime);
                            holder.txt_outtime = (TextView) view
                                    .findViewById(R.id.txt_outtime);
        
                            // the setTag is used to store the data within this view
                            view.setTag(holder);
                        } else {
                            // the getTag returns the viewHolder object set as a tag
                            // to the view
                            holder = (ViewHolder) view.getTag();
                            view = mLayoutInflater.inflate(
                                    R.layout.listview_values, parent, false);
                        }
        
                    }
                    // get the string item from the position "position" from array
                    // list to put it on the TextView
                    String date = attendence_webdata.get(position).get("A_date")
                            .toString();
                    String intime = attendence_webdata.get(position)
                            .get("Ain_time").toString();
                    String outtime = attendence_webdata.get(position)
                            .get("out_time").toString();
                    if (date != null) {
                        if (holder.txt_date != null) {
                            // set the item name on the TextView
                            holder.txt_date.setText(date);
                        }
                    }
                    if (intime != null) {
                        if (holder.txt_intime != null) {
                            // set the item name on the TextView
                            holder.txt_intime.setText(intime);
                        }
                    }
                    if (outtime != null) {
                        if (holder.txt_outtime != null) {
                            // set the item name on the TextView
                            holder.txt_outtime.setText(outtime);
                        }
                    }
        
                    // this method must return the view corresponding to the data at
                    // the specified position.
                    return view;
        
                }
            }
        
        }
        
        /**
         * Static class used to avoid the calling of "findViewById" every time the
         * getView() method is called, because this can impact to your application
         * performance when your list is too big. The class is static so it cache
         * all the things inside once it's created.
         */
        private static class ViewHolder {
            private TextView txt_outtime;
            private TextView txt_intime;
            private TextView txt_date;
        
        }
        
        @Override
        public void onBackPressed() {
            // TODO Auto-generated method stub
            super.onBackPressed();
            attendence_webdata.clear();// where attendence_webdata is arraylistname
            list.setAdapter(null);     //where list is your listview name
        }
        

        检查此代码以了解您何时返回父活动并通过 .clear() 方法清除数据。我在我的应用程序和它的工作中使用了这段代码,所以你可以从这段代码中了解如何管理列表视图中的重复条目

        【讨论】:

          【解决方案7】:
          public View getView(int position, View convertView, ViewGroup parent) {
              LayoutInflater inflater = (LayoutInflater) context
                  .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
              View gridView;
              if (convertView == null) {
                  gridView = new View(context);
              } else {
                  gridView = (View) convertView;
              }
              gridView = inflater.inflate(R.layout.worker_listmain, null);
              // your source code here!!! Run 100%
              return gridView;
          }
          

          【讨论】:

          • 我也遇到了这个问题,我想办法解决!请使用我的源代码:D 简单就是完美:D
          【解决方案8】:

          我认为您应该在活动类的清单文件中添加这一行。 android:windowSoftInputMode="adjustPan"

          【讨论】:

            猜你喜欢
            • 2013-04-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-09-16
            • 2013-10-01
            • 2012-11-20
            • 1970-01-01
            相关资源
            最近更新 更多