列表视图未从具有重复行的数据库中正确填充


Listview is not populated correctly from database with duplicate rows

我正在使用AsyncTask通过JSON数组从mysql数据库填充Listview。问题是我的所有项目都被显示出来,除了最后一行中的列表视图有重复的条目。

我的文件从数据库导出,因为我按升序导出它们

检查这个更好地解释发生了什么

和我的代码:

public class JsonReadTask extends AsyncTask<String , Void, List<ProductList>> {
        public JsonReadTask() {
            super();
        }
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(getActivity(), ProgressDialog.THEME_DEVICE_DEFAULT_DARK);
            pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            pDialog.setMessage(getString(R.string.get_stocks));
            pDialog.setIndeterminate(true);
            pDialog.setCancelable(false);
            pDialog.setInverseBackgroundForced(true);
            pDialog.show();
        }
        @Override
        protected List<ProductList> doInBackground(String... params) {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(params[0]);
            try {
                HttpResponse response = httpclient.execute(httppost);
                jsonResult = inputStreamToString(
                        response.getEntity().getContent()).toString();
                customList = new ArrayList<>();
                JSONObject jsonResponse = new JSONObject(jsonResult);
                //JSONArray jsonMainNode = jsonResponse.optJSONArray("beverages");
                JSONArray array = jsonResponse.getJSONArray("beverages");
                for (int i = 0; i < array.length(); i++) {
                    JSONObject jsonChildNode = array.getJSONObject(i);
                    String name = jsonChildNode.getString("name");
                    String price = jsonChildNode.getString("price");
                    String image = jsonChildNode.getString("image");
                    customList.add(new ProductList(image, name, price));
                }
                return customList;
            } catch (Exception e) {
                e.printStackTrace();
                getActivity().finish();
            }
            return null;
        }
        private StringBuilder inputStreamToString(InputStream is) {
            String rLine = "";
            StringBuilder answer = new StringBuilder();
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            try {
                while ((rLine = rd.readLine()) != null) {
                    answer.append(rLine);
                }
            } catch (Exception e) {
                getActivity().finish();
            }
            return answer;
        }
        @Override
        protected void onPostExecute(List<ProductList> customList) {
            if(customList == null){
                Log.d("ERORR", "No result to show.");
                return;
            }
            ListDrawer(customList);
            pDialog.dismiss();
        }
    }// end async task
    public void accessWebService() {
        JsonReadTask task = new JsonReadTask();
        task.execute(new String[]{url});
    }
    public void ListDrawer(List<ProductList> customList) {
        adapter = new ProductListAdapter(getActivity().getApplicationContext(), R.layout.list_item, customList);
        adapter.notifyDataSetChanged();
        lv.setAdapter(adapter);
    }

我的适配器代码即使我认为是无关紧要的,因为它在咖啡和零食上工作正常:

public class ProductListAdapter extends ArrayAdapter<ProductList> {
    public ProductListAdapter(Context context, int layoutId, List<ProductList> items) {
        super(context, layoutId, items);
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View arrayView = convertView;
        ViewHolderItems holder;
        ProductList currentPosition = null;
        if(arrayView == null){
            LayoutInflater vi;
            vi = LayoutInflater.from(getContext());
            arrayView = vi.inflate(R.layout.list_item, parent, false);
            currentPosition = getItem(position);
            holder = new ViewHolderItems();
            holder.viewName = (TextView)arrayView.findViewById(R.id.product_name_coffee);
            holder.viewPrice = (TextView)arrayView.findViewById(R.id.product_price_coffee);
            holder.viewImage = (ImageView)arrayView.findViewById(R.id.product_image_coffee);
            arrayView.setTag(holder);
        }else{
            holder = (ViewHolderItems) arrayView.getTag();
        }
        if(currentPosition != null){
            holder.viewName.setText(currentPosition.getName());
            holder.viewPrice.setText(currentPosition.getPrice());
            Ion.with(holder.viewImage).placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).load(currentPosition.getImage());
        }
        return arrayView;
    }
    static class ViewHolderItems {
        TextView viewName, viewPrice;
        ImageView viewImage;
    }

}

我的 php 代码:

<?php
try {
    $handler = new PDO('mysql:host=localhost;dbname=database', 'root', 'password');
    $handler->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (Exception $e) {
    echo $e->getMessage();
    die();
}
$query = $handler->query('SELECT * FROM beverages ORDER BY `name` ASC');
$records = array();
$records = $query->fetchAll(PDO::FETCH_ASSOC);
$json['beverages'] = $records;
echo json_encode($json);

知道为什么会这样吗???

看起来问题出在你的getView()方法上,特别是这段代码:

    if(currentPosition != null){
        holder.viewName.setText(currentPosition.getName());
        holder.viewPrice.setText(currentPosition.getPrice());
        Ion.with(holder.viewImage).placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).load(currentPosition.getImage());
    }

仅当currentPosition不为 null 时,才会更新视图的行 - 仅当convertView null时才会发生这种情况。如果行的数据不会更新,它将只使用当前在 convertView 中的内容。这就是为什么有些数据看起来是重复的。

要纠正此问题,您只需删除包装if条件并保留其中的三行不变即可。

尝试在 onCreate() 中初始化适配器

List<ProductList> list;
@Override
public void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    adapter = new ProductListAdapter(getActivity().getApplicationContext(), R.layout.list_item, list);
}
更新用于调用数组适配器构造函数的变量

(在这种情况下,我已经声明了另一个全局变量列表列表并在数组适配器构造函数中传递了此变量)

public void ListDrawer(List<ProductList> customList) {
    list = customList;
    adapter.notifyDataSetChanged();
    lv.setAdapter(adapter);
}

我认为问题出在列表视图适配器的getView方法上。我会这样修改它:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolderItems holder;
    if (convertView == null) {
        LayoutInflater layoutInflater = (LayoutInflater) getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = layoutInflater.inflate(R.layout.list_item, parent, false);
        holder = new ViewHolderItems();
        holder.viewName = (TextView)convertView.findViewById(R.id.product_name_coffee);
        holder.viewPrice = (TextView)convertView.findViewById(R.id.product_price_coffee);
        holder.viewImage = (ImageView)convertView.findViewById(R.id.product_image_coffee);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolderItems) convertView.getTag();
    }

    holder.viewName.setText(getItem(position).getName());
    holder.viewPrice.setText(getItem(position).getPrice());
    Ion.with(holder.viewImage).placeholder(R.drawable.ic_launcher).error(R.drawable.ic_launcher).load(getItem(position).getImage());

    return convertView;
}