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

Listview is not populated correctly from database with duplicate rows

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

我的 File 来自数据库,因为我按升序导出它们

Check this explain better what is happening

还有我的代码:

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);

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

尝试在 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);
}

更新用于调用数组适配器构造函数的变量(在这种情况下,我声明了另一个全局变量 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;
}

看起来问题出在您的 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 不为空时才会更新视图的行——只有当 convertViewnull 时才会发生这种情况。如果该行的数据不会更新,它只会使用当前在 convertView 中的数据。这就是为什么有些数据看起来是重复的。

要更正此问题,只需删除环绕 if 条件并保持其中的三行不变即可。