Android应用中listview中的奇怪故障

时间:2016-04-30 02:25:01

标签: java android android-layout listview

我的应用中有两个奇怪的故障

  1. 使用Listview时,当我再次快速向上滚动时,第一个项目会更改。
  2. 我没有实现会导致这种情况的任何事情,这是一个小问题 列表视图?

    1. 更新Listview时,它会获取数据,当它进行更新时,它会检测前12个项目,然后再次重复它们,然后再重复6个(对于宿舍总数) 我找不到它在12处重复的原因,这里是我的代码
    2. MainActivity类:

      public class MainActivity extends AppCompatActivity {
      
      private Button btnGetData;
      private final String URL = "https://www.laundryalert.com/cgi-bin/urba7723/LMPage?Login=True";
      
      private List<DormMachines> dorms;
      private BaseAdapterDorm dormsAdapter;
      private ListView dormsList;
      
      private ProgressDialog mProgressDialog;
      
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
      
          // Set click listener for button
          btnGetData = (Button) findViewById(R.id.btnContent);
          btnGetData.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  new GetContent().execute();
      
              }
          });         dorms = new ArrayList<DormMachines>();
      
          dormsList = (ListView) findViewById(R.id.myListView);
          dormsAdapter = new BaseAdapterDorm(dorms, this);
      
          dormsList.setAdapter(dormsAdapter);
      
          setupListViewListener();
      }
      
      private void setupListViewListener() {
          dormsList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
              @Override
              public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                  dorms.remove(position);
                  dormsAdapter.notifyDataSetChanged();
              }
          });
      }
      
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          // Inflate the menu; this adds items to the action bar if it is present.
          getMenuInflater().inflate(R.menu.main_menu, menu);
          return true;
      }
      
      private class GetContent extends AsyncTask<Void, Void, Void> {
      
          @Override
          protected void onPreExecute() {
              super.onPreExecute();
              mProgressDialog = new ProgressDialog(MainActivity.this);
              mProgressDialog.setTitle("Getting Content");
              mProgressDialog.setMessage("Loading...");
              mProgressDialog.setIndeterminate(false);
              mProgressDialog.show();
          }
      
          @Override
          protected Void doInBackground(Void... params) {
              dorms.clear();
      
              try {
                  Document doc = Jsoup.connect(URL).get();
                  Element table = doc.getElementById("tableb");
                  Elements rows = table.getElementsByTag("tr");
      
                  // Removes table headers and whitespace at end
                  rows.remove(0);
                  rows.remove(0);
                  rows.remove(30);
      
                  for(Element row : rows) {
                      int index = 0;
                      DormMachines dorm = new DormMachines();
                      for (Element rowData : row.getElementsByTag("td")) {
                          switch (index) {
                              case 1:
                                  // Dorm Name
                                  dorm.dormName = rowData.text();
                                  break;
                              case 2:
                                  // Washers Free
                                  dorm.washersFree = Integer.parseInt(rowData.text());
                                  break;
                              case 3:
                                  // Dryers Free
                                  dorm.dryersFree = Integer.parseInt(rowData.text());
                                  break;
                              case 5:
                                  // Washers in Use
                                  dorm.washersInUse = Integer.parseInt(rowData.text());
                                  break;
                              case 7:
                                  // Dryers In Use
                                  dorm.dryersInUse = Integer.parseInt(rowData.text());
                                  break;
                              default:
                                  break;
      
                          }
                          index++;
                      }
                      dorms.add(dorm);
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              }
              return null;
          }
      
          @Override
          protected void onPostExecute(Void result) {
              dormsAdapter.notifyDataSetChanged();
              mProgressDialog.dismiss();
          }
      }
      

      }

      BaseAdapterDorm类:

      public class BaseAdapterDorm extends BaseAdapter {    
      private List<DormMachines> list;
      private LayoutInflater layoutInflater;
      
      public BaseAdapterDorm(List<DormMachines> list, Context context) {
          this.list = list;
          this.layoutInflater =(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
      }
      
      @Override
      public int getCount() {
          return list.size();
      }
      
      @Override
      public Object getItem(int position) {
          return list.get(position);
      }
      
      @Override
      public long getItemId(int position) {
          return position;
      }
      
      @Override
      public View getView(int position, View view, ViewGroup parent) {
          DormViewHolder dormViewHolder;
      
          if(view == null) {
              view = layoutInflater.inflate(R.layout.listview_dorm_item, parent, false);
      
              dormViewHolder = new DormViewHolder();
      
              dormViewHolder.textViewDormName = (TextView) view.findViewById(R.id.list_item_dorm_item_name);
              dormViewHolder.textViewWasherAvail = (TextView) view.findViewById(R.id.list_item_washers_avail);
              dormViewHolder.textViewWasherOccupied = (TextView) view.findViewById(R.id.list_item_washer_occupied);
              dormViewHolder.textViewDryersAvail = (TextView) view.findViewById(R.id.list_item_dryers_avail);
              dormViewHolder.textViewDryersOccupied = (TextView) view.findViewById(R.id.list_item_dryers_occupied);
      
              dormViewHolder.textViewDormName.setText(list.get(position).dormName);
              dormViewHolder.textViewWasherAvail.setText(""+list.get(position).washersFree);
              dormViewHolder.textViewWasherOccupied.setText(""+list.get(position).washersInUse);
              dormViewHolder.textViewDryersAvail.setText(""+list.get(position).dryersFree);
              dormViewHolder.textViewDryersOccupied.setText(""+list.get(position).dryersInUse);
          }
          return view;
      }
      
      static class DormViewHolder {
          TextView textViewDormName;
          TextView textViewWasherAvail;
          TextView textViewWasherOccupied;
          TextView textViewDryersAvail;
          TextView textViewDryersOccupied;
      }
      

      }

      布局:

          <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical"
          android:padding="8sp"
          tools:context="com.sergiodlz.jsoupexample.MainActivity">
      
          <LinearLayout
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="horizontal">
      
      
              <Button
                  android:layout_width="match_parent"
                  android:layout_height="wrap_content"
                  android:text="Get data"
                  android:id="@+id/btnContent"/>
      
          </LinearLayout>
      
          <ListView
              android:layout_width="match_parent"
              android:layout_height="0sp"
              android:id="@+id/myListView"
              android:layout_weight="1">
      
          </ListView>
      
      
      </LinearLayout>
      

      The rest is on Github

2 个答案:

答案 0 :(得分:0)

这是android中一个众所周知的问题,为了解决这个问题,你需要在列表视图中使用viewholder。发生这种情况的原因是因为列表视图会回收导致这种情况发生的视图

答案 1 :(得分:0)

ListAdapters回收他们的视图(这些视图是列表中的&#34;条目和#34;)。就我们通常所关注的而言,视图的数量是任意的,但在这种情况下,它可能是12。

这个想法是这样的......一旦创建了任意数量的视图(意味着所有视图都是如果(view == null){... create / initialize}),那么每次获得视图在位置Y,您需要替换位置Y处视图的内容,否则您将看到在该视图上被拍过的原始条目的内容。

现在要解决您的问题,请执行以下操作:

public View getView(int position, View view, ViewGroup parent) {
    DormViewHolder dormViewHolder;

    if(view == null) {
        view = layoutInflater.inflate(R.layout.listview_dorm_item, parent, false);

        dormViewHolder = new DormViewHolder();

        dormViewHolder.textViewDormName = (TextView) view.findViewById(R.id.list_item_dorm_item_name);
        dormViewHolder.textViewWasherAvail = (TextView) view.findViewById(R.id.list_item_washers_avail);
        dormViewHolder.textViewWasherOccupied = (TextView) view.findViewById(R.id.list_item_washer_occupied);
        dormViewHolder.textViewDryersAvail = (TextView) view.findViewById(R.id.list_item_dryers_avail);
        dormViewHolder.textViewDryersOccupied = (TextView) view.findViewById(R.id.list_item_dryers_occupied);

        // Set the View Tag with the ViewHolder to save View properties.
        view.setTag(dormViewHolder);
    }
    else
    {
        // Recycle the view (all View properties already set).
        dormViewHolder = (DormViewHolder) view.getTag();
    }

    dormViewHolder.textViewDormName.setText(list.get(position).dormName);
    dormViewHolder.textViewWasherAvail.setText(""+list.get(position).washersFree);
    dormViewHolder.textViewWasherOccupied.setText(""+list.get(position).washersInUse);
    dormViewHolder.textViewDryersAvail.setText(""+list.get(position).dryersFree);
    dormViewHolder.textViewDryersOccupied.setText(""+list.get(position).dryersInUse);
    return view;
}