【问题标题】:Very Weird Behaviour of ListviewListview的非常奇怪的行为
【发布时间】:2013-09-22 20:01:28
【问题描述】:

我以前从未见过类似的情况,但从最近几天开始,我遇到了 Listview 的非常奇怪的行为,直到现在我都无法隔离问题。

我只粘贴我认为必要的代码,稍后我会告诉你我的问题。

/* tell adapter that data is done and stop the more loading progress bar*/ 
public void setDataChanged(boolean type)
{
    isLoadingData = false;
    notifyDataSetChanged();
}

/* If loading is going on size of the adapter will increase to show the additional progress bar*/ 
@Override
public int getCount() {
    int size = friendsModels.size();
    if (isLoadingData) {
        size += 1;
    }
    Log.i("size", String.valueOf(size));//to check size

    return size;
}
/* set loading true and page number of the data items*/ 
public void setLoadingData(boolean isLoadingData, int page) {
    this.isLoadingData = isLoadingData;
    this.page = page;
    notifyDataSetChanged();
}

/* MAX_ITEM number of item returning from rest webservice per page*/ 
@Override
public int getItemViewType(int position) {
    if(isLoadingData && position%MAX_ITEM==0 && position>0)
    {
        if(position/MAX_ITEM==page+1)
        return 1;
    }
    return 0;
}

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    Log.e("getView", "getView");

    EventHolder eventHolder;
    int type = getItemViewType(position);
    LayoutInflater li = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if(convertView==null){
        eventHolder = new EventHolder();
        if(type==0)
        {
            convertView = li.inflate(R.layout.friends_list_items, parent,false);

            eventHolder.name   = (TextView)convertView.findViewById(R.id.textview_friend_name);

            convertView.setTag(eventHolder);

        }
        else if(type==1)
        {
            convertView = li.inflate(R.layout.progress_dialog, parent,false);
            eventHolder.progress = (RelativeLayout)convertView.findViewById(R.id.progress_layout);
            convertView.setTag(eventHolder);
        }
    }
    else
    {
        eventHolder = (EventHolder) convertView.getTag();
        if(type==0)
        {
            setFriends(eventHolder, position);
        }
    }

    return convertView;
}

现在onScroll方法-

@Override
public void onScroll(AbsListView view, int firstVisibleItem,
        int visibleItemCount, int totalItemCount) {
    if(firstVisibleItem + visibleItemCount >= totalItemCount && !loading && totalItemCount%6==0 && totalItemCount>0 && NetworkUtil.isNetworkAvailable(activity))
    {
        loading = true;
        friendsAdapter.setLoadingData(true,pageNo);
        ControllerRequests.getPeople(FragmentClass.this, ++pageNo, search.getText().toString());
    }
}

@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {       
}

虽然当有 5 个或更多项目时一切正常,但随着项目大小减小,假设 1 或 2,但有时 getView 方法不会被调用,尽管日志信息显示我 getCount = 1或 2 但 getView 只是不要被调用。没有模式,我的意思是有时 5 次 getView 被调用它工作正常然后突然就不行了,就像那样。

【问题讨论】:

  • 如果 getView 没有被调用,那么您不应该在屏幕上看到任何内容。问题:1 或 2 项是否占据整个屏幕(或更多),或者内容是否适合屏幕的可见部分?
  • 正是我在屏幕上看不到任何东西,它只是空白。屏幕的可见部分由 6 个项目组成,而 1 或 2 个项目仅占据屏幕的一部分。

标签: android android-listview android-adapter android-scroll


【解决方案1】:

这是一个奇怪的检查:

if(firstVisibleItem + visibleItemCount >= totalItemCount && !loading &&
                totalItemCount%6==0 && totalItemCount>0 && 
                                  NetworkUtil.isNetworkAvailable(activity))

我指的是:

totalItemCount % 6 == 0

因此,除非项目总数始终是 6 的倍数,否则此检查将阻止调用 friendsAdapter.setLoadingData(true,pageNo);。这就是为什么驻留在setLoadingData(boolean, int) 中的语句notifyDataSetChanged(); 不会在totalItemCount % 6 != 0 中执行。

编辑

我也想不出这样的情况:

firstVisibleItem + visibleItemCount > totalItemCount

您可以使用以下方法检查用户是否已到达列表末尾:

firstVisibleItem + visibleItemCount == totalItemCount

【讨论】:

  • 我一定会尝试,但问题是当项目为 6 或更多时我没有任何问题,当只有 1 或 2 个项目时会出现问题。所以setLoadingData(boolean, int) 在这种情况下不会被调用。
  • @mjosh setLoadingdata(boolean, int) 不会被调用,除非您的适配器包含:0、6、12、18 ... 项。在任何其他值上,if check 都不会通过。当您拥有超过 6 个项目时,问题仍然存在。尝试在 if 块中添加此语句 Log.d("IF_CHECK", "if check passed")。使用几个不同的测试用例运行您的应用程序:1 个项目、6 个项目、20 个项目、24 个项目。您会注意到,即使有 20 个项目,也不会输出 Log 语句。我能问一下您为什么要执行此检查吗?
  • see setLoadingdata(boolean, int) 只会在超过 6 个项目时执行,因为服务器为每个 page 提供 6 个项目。
  • @mjosh 我明白了。所以,问题是当服务器只返回 1 或 2 个项目(而不是 6 个)时,这 1 或 2 个项目甚至都不会显示。您能否分享从服务器获取对象并传递给适配器的代码?
  • @mjosh 可能正在烘焙 4.4 版。
猜你喜欢
  • 2016-03-13
  • 2011-03-01
  • 2020-12-02
  • 1970-01-01
  • 2018-04-20
  • 2020-02-09
  • 1970-01-01
  • 2016-12-04
  • 1970-01-01
相关资源
最近更新 更多