【问题标题】:Android Custom ListView not building with VolleyAndroid 自定义 ListView 不使用 Volley 构建
【发布时间】:2016-07-09 01:37:02
【问题描述】:

我正在解析来自公共源的 JSON 数组并将它们插入到自定义 ListView 中。我有 4 节课;

  1. 用于 Volley 请求的 MySingleton

    public class MySingleton {
    private static MySingleton mInstance;
    private RequestQueue mRequestQueue;
    private ImageLoader mImageLoader;
    private static Context mCtx;
    
    private MySingleton(Context context) {
        mCtx = context;
        mRequestQueue = getRequestQueue();
    
        mImageLoader = new ImageLoader(mRequestQueue,
                new ImageLoader.ImageCache() {
                    private final LruCache<String, Bitmap>
                            cache = new LruCache<String, Bitmap>(20);
    
                    @Override
                    public Bitmap getBitmap(String url) {
                        return cache.get(url);
                    }
    
                    @Override
                    public void putBitmap(String url, Bitmap bitmap) {
                        cache.put(url, bitmap);
                    }
                });
    }
    
    public static synchronized MySingleton getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new MySingleton(context);
        }
        return mInstance;
    }
    
    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
        }
        return mRequestQueue;
    }
    
    public <T> void addToRequestQueue(Request<T> req) {
        getRequestQueue().add(req);
    }
    
    public ImageLoader getImageLoader() {
        return mImageLoader;
    }}
    
  2. 游戏列表项

    公共类 GameListItem {

    private String itemName, itemLongDescription, itemShortDescription, itemReleaseDate;
    String releaseyear;
    private int iconID, imageID;
    
    public GameListItem(String itemName, String releaseyear, int iconID) {
    
        this.itemName = itemName;
        this.releaseyear = releaseyear;
        this.iconID = iconID;
    }
    
    public String getItemName() {
    
        return itemName;
    }
    
    public String getReleaseyear() {
        return releaseyear;
    }}
    
  3. 自定义列表适配器

    公共类 CustomListAdapter 扩展 BaseAdapter {

    private Context mContext;
    private LayoutInflater mInflater;
    private List<GameListItem> mDataSource;
    
    public CustomListAdapter(Context context, List<GameListItem> items) {
        mContext = context;
        mDataSource = items;
        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    
    
    @Override
    public int getCount() {
        return mDataSource.size();
    }
    
    @Override
    public Object getItem(int position) {
        return mDataSource.get(position);
    }
    
    @Override
    public long getItemId(int position) {
        return position;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = mInflater.inflate(R.layout.gamelist_layout, parent, false);
    
        TextView titleTextView = (TextView) rowView.findViewById(R.id.gameTitle);
    
        TextView subtitleTextView = (TextView) rowView.findViewById(R.id.gameDescription);
    
        titleTextView.setText(mDataSource.get(position).getItemName());
        subtitleTextView.setText(mDataSource.get(position).getReleaseyear());
    
        return rowView;
    }}
    
  4. 主活动

    公共类 MainActivity 扩展 AppCompatActivity {

    final String TAG = this.getClass().getSimpleName();
    RequestQueue requestQueue;
    private CustomListAdapter adapter;
    private List<GameListItem> gameList;
    private GameListItem gameItem;
    ListView listView;
    
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    
        Cache cache = new DiskBasedCache(getCacheDir(), 1024*1024);
        Network network = new BasicNetwork(new HurlStack());
        requestQueue = new RequestQueue(cache, network);
        requestQueue.start();
        listView = (ListView) findViewById(R.id.gameListView);
        gameList = new ArrayList<>();
    
        //This works and gives me a ListView with 5 rows
        gameList.add(new GameListItem("Test 1", "2019", R.mipmap.ic_launcher));
        gameList.add(new GameListItem("Test 2", "2092", R.mipmap.ic_launcher));
        gameList.add(new GameListItem("Test 3", "3243", R.mipmap.ic_launcher));
        gameList.add(new GameListItem("Test 4", "2323", R.mipmap.ic_launcher));
        gameList.add(new GameListItem("Test 5", "2123", R.mipmap.ic_launcher));
    
    
        //This doesn't work...
        String url = "http://api.androidhive.info/json/movies.json";
        JsonArrayRequest stringRequest = new JsonArrayRequest(url, new Response
                .Listener<JSONArray>(){
    
            @Override
            public void onResponse(JSONArray jsonArray) {
    
                if (jsonArray == null) {
                    Toast.makeText(MainActivity.this, "jsonArray is Null", Toast.LENGTH_LONG).show();
                } else {
                    try {
                        Toast.makeText(MainActivity.this, "ATTEMPTING PARSING", Toast.LENGTH_SHORT).show();
                        Log.e("This is the json array", jsonArray.toString());
    
                        for (int i = 0; i < jsonArray.length(); i++){
    
                            JSONObject jsonObject = jsonArray.getJSONObject(i);
                            String title = jsonObject.getString("title");
                            int releaseYear = jsonObject.getInt("releaseYear");
    
                            gameList.add(new GameListItem(releaseDate, "" + releaseYear , R.mipmap.ic_launcher));
    
                            //this prints all the Titles and Release Dates correctly
                            Log.e("This is a title", title);
                            Log.e("This is a year", "HERE " + releaseYear);
    
    
    
                        }
    
                    } catch(JSONException e){
                        Log.i("JSON exception", e.toString());
                        Toast.makeText(MainActivity.this, "JSON ERROR", Toast.LENGTH_LONG).show();
                    }
    
                    requestQueue.stop();
                }
    
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
    
                Log.d("This is an error", ""+error.getMessage()+","+error.toString());
            }
        });
    
    
        MySingleton.getInstance(this).addToRequestQueue(stringRequest);
    
        adapter = new CustomListAdapter(this, gameList);
        listView.setAdapter(adapter);
    
    
    }}
    

正如在主要活动中所评论的,当我手动添加一行(使用手动数据)时,ListView 会构建并显示,但解析器没有显示任何内容。 我检查了无数的教程,一切似乎都井井有条,我什至看了这里并遵循了大部分答案,但一无所获。 有人可以看到导致列表无法构建/打印的错误吗?

PS。 Log.e 也会打印(在解析器中)

谢谢!

【问题讨论】:

  • 你有日志吗?请求结果是成功还是错误?如果请求成功,您必须通知适配器数据更改。在你的情况下 adapter.notifyDataSetChanged();在 onResponse 中的 catch 块之前。
  • 嘿,结果成功了,你实际上解决了我的问题,你可以把它写成答案,我会接受的。我居然到处找了半天的解决方案,非常感谢……我感激不尽!我添加了那行,就是这样!

标签: java android json listview android-volley


【解决方案1】:

如果请求成功,您必须通知适配器数据更改。在你的情况下 adapter.notifyDataSetChanged();在 onResponse 中的 catch 块之前。

【讨论】:

    【解决方案2】:

    requestQueue.stop 语句之后添加以下行:

    adapter.notifyDataSetChanged();
    

    一开始,当你设置适配器时,列表没有数据,因为Volley请求会异步进行,所以你需要让适配器知道它的数据何时发生变化。

    来自the documentation

    notifyDataSetChanged()

    通知附加的观察者底层数据已更改,任何反映数据集的视图都应自行刷新。

    【讨论】:

    • 谢谢大家,只是为了让大家知道,它在requestQueue.stop();之后也有效
    猜你喜欢
    • 2015-08-04
    • 1970-01-01
    • 2016-01-01
    • 2012-01-21
    • 1970-01-01
    • 2012-06-01
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多