【问题标题】:Cannot update ListView adapter in the Volley request listener in Android无法在 Android 的 Volley 请求侦听器中更新 ListView 适配器
【发布时间】:2016-05-09 14:10:09
【问题描述】:

我是 Android 新手。现在我开始开发一个项目。在我的项目中,我正在使用 Volley 网络库的列表视图。而且我无法更新适配器并且列表视图没有显示任何内容。

这是我的带有列表视图和 Volley 请求的片段:

public class PodcastListFragment extends Fragment {
    private View view;
    private SwipeRefreshLayout refreshLayout;
    private ListView listView;
    private int channelId;
    private ArrayAdapter adapter;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.podcast_list_fragment,container,false);
        adapter = new PodcastListAdapter(getActivity(),new ArrayList<Podcast>());
        listView = (ListView)view.findViewById(R.id.listview_podcast_list);
        listView.setAdapter(adapter);
        TextView textView = (TextView)view.findViewById(R.id.list_title);
        textView.setText(getArguments().getString("title"));
        this.channelId = getArguments().getInt("channel");
        updateListItems();
        return view;
    }

    private void updateListItems()
    {
        String url = getResources().getString(R.string.api_endpoint)+"podcast";
        if(channelId>0)
        {
            url = url + "?channel="+String.valueOf(channelId);
        }

        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                try{
                    String status = response.getString("status");
                    if(status.equals(getResources().getString(R.string.success)))
                    {
                        JSONArray items = response.getJSONArray("items");
                        ArrayList<Podcast> podcasts = new ArrayList<Podcast>();
                        if(items.length()>0)
                        {
                            for(int i=0;i<items.length();i++)
                            {
                                Podcast podcast = Podcast.fromJsonObject(items.getJSONObject(i));
                                podcasts.add(podcast);
                            }
                        }
                        adapter.addAll(podcasts);
                        adapter.notifyDataSetChanged();
                    }
                }
                catch (JSONException e)
                {
                    Toast.makeText(getActivity().getBaseContext(),"Error encountered in transferring data from server",Toast.LENGTH_SHORT).show();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(getActivity().getBaseContext(),"Error encountered in transferring data from server",Toast.LENGTH_SHORT).show();
            }
        });

        MySingleton.getInstance(getActivity()).addToRequestQueue(jsonObjectRequest);
    }
}

这是我的自定义适配器类:

public class PodcastListAdapter extends ArrayAdapter<Podcast> {
    private final ArrayList<Podcast> values;
    private final Context context;

    static class ViewHolder {
        public TextView titleTextView;
        public TextView descriptionTextView;
        public ImageView imageView;
        public TextView durationTextView;
        public TextView fileSizeTextView;
    }


    public PodcastListAdapter(Context context,ArrayList<Podcast> values)
    {
        super(context,-1,values);
        this.context = context;
        this.values = values;
    }
    @Override
    public View getView(final int position,View convertView,ViewGroup parent)
    {
        View rowView = convertView;

        if(rowView==null)
        {
            LayoutInflater layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            rowView = layoutInflater.inflate(R.layout.podcast_list_row,null);

            ViewHolder viewHolder = new ViewHolder();
            viewHolder.descriptionTextView = (TextView)rowView.findViewById(R.id.row_description);
            viewHolder.titleTextView = (TextView)rowView.findViewById(R.id.row_title);
            viewHolder.durationTextView = (TextView)rowView.findViewById(R.id.row_duration);
            viewHolder.fileSizeTextView = (TextView)rowView.findViewById(R.id.row_file_size);
            viewHolder.imageView = (ImageView)rowView.findViewById(R.id.row_image);
            rowView.setTag(viewHolder);
        }
        ViewHolder holder = (ViewHolder) rowView.getTag();
        holder.titleTextView.setText(values.get(position).getTitle());
        holder.descriptionTextView.setText(values.get(position).getDescription());
        holder.durationTextView.setText(values.get(position).getDuration());
        holder.fileSizeTextView.setText(String.valueOf(values.get(position).getFileSize()));
        return rowView;
    }

}

这是我的播客课:

public class Podcast {
    private int Id;
    private String Title;
    private String Description;
    private String ThumbImagePath;
    private String FilePath;
    private String Duration;
    private int FileSize;

    public static Podcast fromJsonObject(JSONObject json)
    {
        Podcast podcast = new Podcast();
        try{
            podcast.setId(json.getInt("id"));
            podcast.setTitle(json.getString("title"));
            podcast.setDescription(json.getString("description"));
            podcast.setFilePath(json.getString("file_path")+"/"+json.getString("file_name"));
            podcast.setDuration(json.getString("duration"));
            podcast.setThumbImagePath(json.getString("image_path")+"/"+json.getString("image_name"));
            podcast.setFileSize(json.getInt("file_size"));
        }
        catch (JSONException e)
        {
            return null;
        }
        return podcast;
    }

    public void setId(int id)
    {
        this.Id = id;
    }

    public int getId()
    {
        return this.Id;
    }

    public void setTitle(String title)
    {
        this.Title = title;
    }

    public String getTitle()
    {
        return this.Title;
    }

    public void setDescription(String description)
    {
        this.Description = description;
    }

    public String getDescription()
    {
        return this.Description;
    }

    public void setThumbImagePath(String path)
    {
        this.ThumbImagePath = path;
    }

    public String getThumbImagePath()
    {
        return this.ThumbImagePath;
    }

    public void setFilePath(String filePath)
    {
        this.FilePath = filePath;
    }

    public String getFilePath()
    {
        return this.FilePath;
    }

    public void setDuration(String duration)
    {
        this.Duration = duration;
    }

    public String getDuration()
    {
        return this.Duration;
    }

    public void setFileSize(int size)
    {
        this.FileSize = size;
    }

    public int getFileSize()
    {
        return this.FileSize;
    }
}

我的问题是无法向适配器添加新数据,因此 listview 什么也没有显示。但我已经检查过响应返回 10 条记录。我的代码有什么问题?

这是我运行该片段时的 logcat。

02-01 07:42:54.248 29393-29393/? D/dalvikvm: Late-enabling CheckJNI
02-01 07:42:54.276 29393-29399/? D/dalvikvm: Debugger has detached; object registry had 1 entries
02-01 07:42:54.328 29393-29393/? W/dalvikvm: VFY: unable to find class referenced in signature (Landroid/view/SearchEvent;)
02-01 07:42:54.328 29393-29393/? I/dalvikvm: Could not find method android.view.Window$Callback.onSearchRequested, referenced from method android.support.v7.view.WindowCallbackWrapper.onSearchRequested
02-01 07:42:54.328 29393-29393/? W/dalvikvm: VFY: unable to resolve interface method 17990: Landroid/view/Window$Callback;.onSearchRequested (Landroid/view/SearchEvent;)Z
02-01 07:42:54.328 29393-29393/? D/dalvikvm: VFY: replacing opcode 0x72 at 0x0002
02-01 07:42:54.328 29393-29393/? I/dalvikvm: Could not find method android.view.Window$Callback.onWindowStartingActionMode, referenced from method android.support.v7.view.WindowCallbackWrapper.onWindowStartingActionMode
02-01 07:42:54.328 29393-29393/? W/dalvikvm: VFY: unable to resolve interface method 17994: Landroid/view/Window$Callback;.onWindowStartingActionMode (Landroid/view/ActionMode$Callback;I)Landroid/view/ActionMode;
02-01 07:42:54.328 29393-29393/? D/dalvikvm: VFY: replacing opcode 0x72 at 0x0002
02-01 07:42:54.364 29393-29393/? I/AppCompatViewInflater: app:theme is now deprecated. Please move to using android:theme instead.
02-01 07:42:54.372 29393-29393/? I/dalvikvm: Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method android.support.v7.widget.TintTypedArray.getChangingConfigurations
02-01 07:42:54.372 29393-29393/? W/dalvikvm: VFY: unable to resolve virtual method 436: Landroid/content/res/TypedArray;.getChangingConfigurations ()I
02-01 07:42:54.372 29393-29393/? D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
02-01 07:42:54.372 29393-29393/? I/dalvikvm: Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.widget.TintTypedArray.getType
02-01 07:42:54.372 29393-29393/? W/dalvikvm: VFY: unable to resolve virtual method 458: Landroid/content/res/TypedArray;.getType (I)I
02-01 07:42:54.372 29393-29393/? D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
02-01 07:42:54.388 29393-29396/? D/dalvikvm: GC_CONCURRENT freed 200K, 12% free 2596K/2928K, paused 1ms+1ms, total 5ms
02-01 07:42:54.404 29393-29393/? D/dalvikvm: GC_FOR_ALLOC freed 73K, 10% free 2789K/3076K, paused 3ms, total 4ms
02-01 07:42:54.412 29393-29393/? D/dalvikvm: GC_FOR_ALLOC freed 103K, 12% free 2914K/3300K, paused 5ms, total 6ms
02-01 07:42:54.412 29393-29393/? I/dalvikvm-heap: Grow heap (frag case) to 4.043MB for 1127532-byte allocation
02-01 07:42:54.416 29393-29406/? D/dalvikvm: GC_FOR_ALLOC freed <1K, 9% free 4015K/4404K, paused 4ms, total 4ms
02-01 07:42:54.420 29393-29396/? D/dalvikvm: GC_CONCURRENT freed <1K, 9% free 4015K/4404K, paused 1ms+0ms, total 3ms
02-01 07:42:54.432 29393-29393/? D/dalvikvm: GC_FOR_ALLOC freed <1K, 9% free 4015K/4404K, paused 8ms, total 8ms
02-01 07:42:54.436 29393-29393/? I/dalvikvm-heap: Grow heap (frag case) to 6.463MB for 2536932-byte allocation
02-01 07:42:54.452 29393-29406/? D/dalvikvm: GC_FOR_ALLOC freed 0K, 6% free 6492K/6884K, paused 16ms, total 16ms
02-01 07:42:54.452 29393-29396/? D/dalvikvm: GC_CONCURRENT freed 0K, 6% free 6492K/6884K, paused 2ms+1ms, total 4ms
02-01 07:42:54.504 29393-29393/? D/libEGL: loaded /system/lib/egl/libEGL_genymotion.so
02-01 07:42:54.508 29393-29393/? D/: HostConnection::get() New Host Connection established 0xb79491c0, tid 29393
02-01 07:42:54.516 29393-29393/? D/libEGL: loaded /system/lib/egl/libGLESv1_CM_genymotion.so
02-01 07:42:54.516 29393-29393/? D/libEGL: loaded /system/lib/egl/libGLESv2_genymotion.so
02-01 07:42:54.572 29393-29393/? W/EGL_genymotion: eglSurfaceAttrib not implemented
02-01 07:42:54.596 29393-29393/? D/OpenGLRenderer: Enabling debug mode 0
02-01 07:42:54.612 29393-29393/? I/dalvikvm: Could not find method android.content.res.Resources.getDrawable, referenced from method android.support.v7.widget.ResourcesWrapper.getDrawable
02-01 07:42:54.612 29393-29393/? W/dalvikvm: VFY: unable to resolve virtual method 399: Landroid/content/res/Resources;.getDrawable (ILandroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
02-01 07:42:54.612 29393-29393/? D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
02-01 07:42:54.612 29393-29393/? I/dalvikvm: Could not find method android.content.res.Resources.getDrawableForDensity, referenced from method android.support.v7.widget.ResourcesWrapper.getDrawableForDensity
02-01 07:42:54.612 29393-29393/? W/dalvikvm: VFY: unable to resolve virtual method 401: Landroid/content/res/Resources;.getDrawableForDensity (IILandroid/content/res/Resources$Theme;)Landroid/graphics/drawable/Drawable;
02-01 07:42:54.612 29393-29393/? D/dalvikvm: VFY: replacing opcode 0x6e at 0x0002
02-01 07:42:54.836 29393-29393/? I/dalvikvm: Could not find method android.support.v7.widget.LinearLayoutCompat.drawableHotspotChanged, referenced from method android.support.design.internal.ForegroundLinearLayout.drawableHotspotChanged
02-01 07:42:54.836 29393-29393/? W/dalvikvm: VFY: unable to resolve virtual method 14714: Landroid/support/v7/widget/LinearLayoutCompat;.drawableHotspotChanged (FF)V
02-01 07:42:54.836 29393-29393/? D/dalvikvm: VFY: replacing opcode 0x6f at 0x0000

【问题讨论】:

  • 你查过logcat,有没有异常?
  • 您的网络 api 调用的响应是什么?是成功/失败吗?错误是什么?
  • 我刚刚用 logcat 更新了问题,我认为 logcat 中没有与适配器和 volley 相关的错误
  • 我的api调用成功
  • 你检查过items的长度吗?

标签: android listview android-volley android-adapter


【解决方案1】:

根本原因是 -

private final ArrayList<Podcast> values

适配器中的 values 未使用响应中的新对象进行更新。你应该检查一下。

将所需的public 方法addAll() 添加到您自己的ArrayAdapter 实现中,您无法看到android.widget.ArrayAdapter 中的私有成员,因此需要使用现有的公共API ArrayAdapter.add() 来添加其中的每个元素一个循环。但请记住,每个add() 都会产生notifyDataSetChanged(),这可能会导致崩溃,具体取决于添加的数量。

所以总结是你需要在你的实现中实现你自己的addAll()。或者你可以想出你自己的方法。有很多方法可以做到这一点。

更新

你需要覆盖 -

@Override
public int getCount () {
     return values.size();    
}

【讨论】:

  • 我试过 add 。它不工作。我认为这不是问题。因为 addAll 在我之前的教程项目中工作,因为我扩展了 ArrayAdapter。
  • @WaiYanHein,如果您 100% 确定您的新对象已添加到值中,请尝试使用我更新的答案。
  • 你试过删除“final”吗?
【解决方案2】:

请在发送 PodcastListAdapter 类之前填写 arrayList 并在代码下方使用适配器。

 if (adapter != null)
    adapter.notifyDataSetChanged();
 else {
     adapter = new PodcastListAdapter(getActivity(),new ArrayList<Podcast>());
     listView.setAdapter(adapter);
 }

【讨论】:

  • 从他提供的代码来看,不需要检查适配器是否为空,因为它总是为空。
  • 如果适配器 obj 为空,他现在应该有 NPE
【解决方案3】:

ArrayAdapter 构造函数中,为什么要传递 -1 ?在超级构造函数中传递R.layout.podcast_list_row。并在getView 中使用相同的内容。

super(context,R.layout.podcast_list_row,values);

编辑:

在适配器构造函数adapter 中传递ArrayList&lt;Podcast&gt; 的一个实例@ podCastList 在onCreateViewonResponse 中向该实例podCastList.addAll(items) 添加新值,然后调用notifyDataSetChanged

public class PodcastListFragment extends Fragment {
private View view;
private SwipeRefreshLayout refreshLayout;
private ListView listView;
private int channelId;
private ArrayAdapter adapter;
private ArrayList<Podcast>podcastList = new ArrayList<Podcast>()

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    view = inflater.inflate(R.layout.podcast_list_fragment,container,false);
    adapter = new PodcastListAdapter(getActivity(),podcastList);
    listView = (ListView)view.findViewById(R.id.listview_podcast_list);
    listView.setAdapter(adapter);
    TextView textView = (TextView)view.findViewById(R.id.list_title);
    textView.setText(getArguments().getString("title"));
    this.channelId = getArguments().getInt("channel");
    updateListItems();
    return view;
}

private void updateListItems()
{
    String url = getResources().getString(R.string.api_endpoint)+"podcast";
    if(channelId>0)
    {
        url = url + "?channel="+String.valueOf(channelId);
    }

    JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(url, null, new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            try{
                String status = response.getString("status");
                if(status.equals(getResources().getString(R.string.success)))
                {
                    JSONArray items = response.getJSONArray("items");
                    ArrayList<Podcast> podcasts = new ArrayList<Podcast>();
                    if(items.length()>0)
                    {
                        for(int i=0;i<items.length();i++)
                        {
                            Podcast podcast = Podcast.fromJsonObject(items.getJSONObject(i));
                            podcasts.add(podcast);
                        }
                    }
                    podcastList.addAll(podcasts);
                    adapter.notifyDataSetChanged();
                }
            }
            catch (JSONException e)
            {
                Toast.makeText(getActivity().getBaseContext(),"Error encountered in transferring data from server",Toast.LENGTH_SHORT).show();
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Toast.makeText(getActivity().getBaseContext(),"Error encountered in transferring data from server",Toast.LENGTH_SHORT).show();
        }
    });

    MySingleton.getInstance(getActivity()).addToRequestQueue(jsonObjectRequest);
}
}

【讨论】:

  • 你能放一些调试指针并检查getView是否被调用?
  • 他的 getView() 没有被调用。
【解决方案4】:

我发现了错误。我也应该发布片段 xml 布局文件。问题是我将列表视图布局放在滑动刷新布局中。这就是问题所在。

这是我的旧 xml 布局文件

<android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/podcast_list_refresh_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <TextView
            android:id="@+id/list_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <ListView
            android:id="@+id/listview_podcast_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"></ListView>
    </android.support.v4.widget.SwipeRefreshLayout>

这就是我删除 SwipeRefreshLayout 的方法

<TextView
    android:id="@+id/list_title"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
<ListView
    android:id="@+id/listview_podcast_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"></ListView>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    • 2020-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多