动态增加列表视图中的元素数量

时间:2012-04-14 08:40:37

标签: android android-listview dynamic-data

当列表视图滚动到最后时,我想增加列表视图将动态显示的项目数。 在我的情况下,我的listview最初将显示10个项目。然后当我们滚动到最后一个项目时,它必须开始显示另外10个项目,依此类推。 我怎么能这样做?

这是我的自定义数组适配器

    package com.android.listview;

import java.util.ArrayList;

import com.android.listview.R;
import com.android.listview.Product;

import android.widget.ArrayAdapter;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.android.listview.ListViewActivity;

public class CustomArrayAdapter extends ArrayAdapter<Product> implements
        OnScrollListener {

    private final Context context;
    private final ArrayList<Product> values;

    static class ViewHolder {
        public TextView text;
        public ImageView image;
    }

    public CustomArrayAdapter(Context arg0, int arg1, int arg2,
            ArrayList<Product> arg3) {
        super(arg0, arg1, arg2, arg3);
        this.context = arg0;
        this.values = arg3;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        int product_id = 0;
        View rowView = inflater.inflate(R.layout.feed_items, parent, false);
        try {

            ImageView wic_logo = (ImageView) rowView.findViewById(R.id.logo);
            TextView label = (TextView) rowView.findViewById(R.id.label);

            Product p = values.get(position);
            product_id = p.productId;
            String date = new java.text.SimpleDateFormat("dd/MM/yy")
                    .format(new java.util.Date(p.timeStamp));
            label.setText(p.productName + "\n" + p.reportedPrice + "   MRP: "
                    + p.mrp + "\n" + "Discount: " + p.discount + "%   "
                    + p.area + "  " + p.city + "\n" + "Shared by " + p.userName
                    + " " + "on" + " " + date);

            wic_logo.setImageResource(R.drawable.wic_logo_small);
            Log.d("date", "" + date);

            Log.d("Custom Array Adapter", "at" + position);
        } catch (Exception e) {
            Log.d("Custom Array Adapter", "catch");
        }

        return rowView;
    }

    public void onScroll(AbsListView arg0, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        Log.d("entered onScroll", " " + firstVisibleItem + visibleItemCount
                + totalItemCount);
        if (((firstVisibleItem + visibleItemCount) >= totalItemCount - 1)) {
            Log.d("entered if", " " + firstVisibleItem + visibleItemCount
                    + totalItemCount);
            // if we're at the bottom of the listview, load more data
            addData(totalItemCount, values.get(totalItemCount).productId);
        }
    }

    private void addData(int totalItemCount, int productId) {

        Toast.makeText(getContext(), "last item", Toast.LENGTH_SHORT).show();
    }

    public void onScrollStateChanged(AbsListView arg0, int arg1) {

    }
}

这是我的活动

package com.android.listview;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.android.listview.CustomArrayAdapter;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Button;
import android.widget.ListView;

public class ListViewActivity extends Activity {

    static Product[] feed_products_list;
    private JSONArray JArray;
    private InputStream is;
    private StringBuilder sb;
    private String result;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button feed_button = (Button) findViewById(R.id.feedButton_feed);
        feed_button.setBackgroundResource(R.color.grey);
        ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost("http://10.0.2.2/wic2/mobile/feed");
            httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
            ResponseHandler<String> responseHandler = new BasicResponseHandler();
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            is = entity.getContent();

            try {
                BufferedReader reader = new BufferedReader(
                        new InputStreamReader(is, "iso-8859-1"), 8);
                sb = new StringBuilder();
                sb.append(reader.readLine() + "\n");
                String line = "0";
                while ((line = reader.readLine()) != null) {
                    sb.append(line + "\n");
                }
                is.close();
                result = sb.toString();
                Log.d("result", result);
            } catch (Exception e) {
                Log.e("error", "Error in http connection" + e.toString());
            }

            Log.e("response", "response is:" + response.toString());
        } catch (Exception e) {
            Log.e("error", "Error in http connection" + e.toString());
        }

        ListView tv = (ListView) findViewById(R.id.feedListView);
        try {
            Log.d("JArray", "entered try");
            JArray = new JSONArray(result);
            int length = JArray.length();
            feed_products_list = new Product[length+1];
            Log.d("JArray", "try last line");
        } catch (JSONException e) {
            Log.d("JArray", "in catch");
            e.printStackTrace();
        }

        JSONObject jsonObj;

        for (int i = 0; i < JArray.length(); i++) {
            try {
                Log.d("jsonObj", "entered try");
                jsonObj = JArray.getJSONObject(i);
            } catch (Exception e) {
                Log.d("jsonObj", "in catch");
                continue;
            }

            try {
                Log.d("feed_products_list", "entered try");
                feed_products_list[i] = new Product(jsonObj.getInt("id"),
                        jsonObj.getString("image"),
                        jsonObj.getString("product_name"),
                        jsonObj.getString("reported_price_formated"),
                        jsonObj.getString("store_area"),
                        jsonObj.getString("store_city"),
                        jsonObj.getString("mrp"),
                        jsonObj.getString("user_name"),
                        jsonObj.getLong("reported_timestamp"),
                        jsonObj.getInt("discount"));
                Log.d("feed_products_list", feed_products_list[i].productName);
            } catch (JSONException e) {
                Log.d("feed_products_list in catch",
                        feed_products_list[i].productName);
                e.printStackTrace();
            }
        }

        tv.setAdapter(new CustomArrayAdapter(this, R.layout.feed_items,
                R.id.label, feed_products_list));


    }
}

还有一个问题是我必须使用JArray中的项目数初始化我的数组feed_products_list [length]。因此,每次滚动到最后一项并再次重新填充整个列表时,我都无法更改数组大小

6 个答案:

答案 0 :(得分:3)

首先,您的代码存在一些问题。在Activity中,将变量values更改为ArrayList<Product>,因为您无法在创建后操纵数组的长度。接下来,将JArray重命名为jArray;如果第一个字母是一个资本,表明你正在处理一个类而不是一个变量。

此外,您没有使用ViewHolder模式,这极大地提高了性能。查看this link on vogella.com about ListView;更具体地说,查看第3.1和3.2章

CustomArrayAdapter中,实施OnScrollListener并添加所需的方法。然后,在onScroll(...)中,确定是否要添加数据(例如,用户已到达列表底部)。最后,加载新项目,将其添加到数据集中values.add(product)values.addAll(products),其中产品为ListProduct,并从内部调用notifyDataSetChanged每次致电CustomArrayAdaptervalues.add(...)后,您的values.addAll(...)

例如,您可以在代码中更改以下内容:

活动

  • 删除行

    int length = JArray.length();
    feed_products_list = new Product[length+1];
    
  • feed_products_list中删除'static'并将其更改为ArrayList:

    private ArrayList<Product> feed_products_list = new ArrayList<Product>();
    
  • 而不是feed_products_list[i] = new Product(jsonObj.getInt("id"), .... yadiya ...,请调用feed_products_list.add(新产品(jsonObj.getInt(“id”),... yadiya ...`。

适配器

  • 制作课程implement OnScrollListener,并将onScroll() - 方法设置为以下内容:

    public void onScroll(AbsListView view, int firstVisibleItem,
                            int visibleItemCount, final int totalItemCount) {
        if(((firstVisibleItem + visibleItemCount) >= totalItemCount)) {
    
            // if we're at the bottom of the listview, load more data
            addData(totalItemCount);
        }
    }
    
  • 创建方法addData(long offset)

    private void addData(long offset) {
    
        // download your data, pass the offset so you know where to start
        // and when you convert your json into `Product`s
        Product product = new Product(JSONObject.getInt("id"), ... yadiya ...);
        this.add(product);
        this.notifyDataSetChanged();
    
        // make sure to call notifyDataSetChanged() on your UI-Thread.
    }
    

答案 1 :(得分:2)

为了动态增加大小,最好使用ArrayList。对于滚动,你可以使用@Mayank的想法。

答案 2 :(得分:1)

您应该将scroll listener附加到listview

ListView lv = (ListView)findViewById(R.id.list_view); 
lv.setOnScrollListener(new OnScrollListener() { 
    @Override 
    public void onScroll(AbsListView view, int firstVisibleItem,  
        int visibleItemCount, int totalItemCount) { 
        //Check if the last view is visible 
        if (view.getLastVisiblePosition()+1 == 10) { 
            //load more content 
        } 
    } 
});

<强>更新

因此,最初在您的feed_products_list中,您有10个项目,当用户向下滚动时,在列表中再添加10个项目并将CustomArrayAdapter重置为listView。继续这样做,直到你有列表中的所有项目。

答案 3 :(得分:0)

您不需要这样做。 Android列表视图可以轻松处理数千个条目 - 前提是您仔细编写适配器并重用视图。因此,在你的getView()方法中,你必须检查converView是否是正确的,然后用新值填充它。 (Andriod非常聪明,它提供回收目前不可见的列表条目) - 这将为您提供即时性能提升

这样做:

View rowView = convertView;
if(rowView == null) {
   // do what you are doing now to inflate view
}
// do what you are doing now to set up view

return rowView;

如果您不想加载所有条目,则增加列表大小是有意义的 无论你立即存储什么 - 在这种情况下你必须注册滚动监听器并通过加载缺少的条目对其作出反应,然后发信号通知列表数据已更改。而且您不必使用数组作为后备存储 - 列表将完全匹配此目的

答案 4 :(得分:0)

使用ArrayList而不是array 像这样

public class CustomArrayAdapter extends ArrayAdapter<Object> {

    private final Context context;
    private final ArrayList<Product> values;

并在getView()

            Product p = values.get(position);

你可以在你的适配器中提供一个方法来向ArrayList添加元素,notifyDataSetChange()它看起来像这样

public void addElement(Product p){
values.add(p);
notifiyDataSetChange();
}

使用OnScrollListener加载更多数据 例如:

listView.setOnScrollListener(new OnScrollListener() { 
    @Override 
    public void onScroll(AbsListView view, int firstVisibleItem,  
        int visibleItemCount, int totalItemCount) { 

        if (totalItemCount - visibleItemCount <= firstVisibeItem + 5) { 
            //load more content 

            .....
            adpater.addElement(p);

        } 


     } 
    });

答案 5 :(得分:0)

我想你想要像Lazy loading这样的东西。

它被称为延迟加载。我相信你没有尝试过这样的搜索。我给你了GridView的例子。这是Listview Other Link

的其他链接