Cannot update ListView adapter in the Volley reque

2019-08-08 21:11发布

I am new to Android. Now I start developing a project. In my project I am working list view with Volley network library. And I cannot update the adapter and list view is showing nothing.

This is my Fragment with listview and Volley request:

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);
    }
}

This is my custom adapter class:

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;
    }

}

This is my podcast class:

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;
    }
}

My problem is cannot add new data to adapter and so listview is showing nothing. But I already checked response is returning 10 records. What is wrong with my code?

This is the logcat when I run that fragment.

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

4条回答
SAY GOODBYE
2楼-- · 2019-08-08 21:34

Please fill arrayList before send PodcastListAdapter class and use adapter below code.

 if (adapter != null)
    adapter.notifyDataSetChanged();
 else {
     adapter = new PodcastListAdapter(getActivity(),new ArrayList<Podcast>());
     listView.setAdapter(adapter);
 }
查看更多
闹够了就滚
3楼-- · 2019-08-08 21:41

I found the error. I should have posted the fragment xml layout file as well. The problem was I put the list view layout inside swipe refresh layout. That is the problem.

This is my old xml layout file

<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>

This is how I fixed it removing the 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>
查看更多
对你真心纯属浪费
4楼-- · 2019-08-08 21:43

In the ArrayAdapter constructor why are you passing -1 ? Pass R.layout.podcast_list_row in super constructor. And use the same in getView.

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

Edit:

Pass an instance of ArrayList<Podcast> say podCastList in adapter constructor adapter in onCreateView and in onResponse add new values to that instance podCastList.addAll(items) then call 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);
}
}
查看更多
贼婆χ
5楼-- · 2019-08-08 21:44

Root cause is -

private final ArrayList<Podcast> values

your valuesin the adapter are not updating with the new objects from the response. You should check that.

add the required public method addAll() to your own ArrayAdapter implementation, you don't have the visibility on private member in android.widget.ArrayAdapter so need use existing public API ArrayAdapter.add() to add every single element within a loop. But remember, each add() will result notifyDataSetChanged() which might lead to crash depending on the number of addition.

So the sum up is you need to implement your own addAll() in your implementation. Or you can come up with your own method. There are plenty of ways to do that.

Update

You need to override -

@Override
public int getCount () {
     return values.size();    
}
查看更多
登录 后发表回答