I am trying to fetch JSON data from mySQL to android app, following this. I am getting this error E/RecyclerView: No adapter attached; skipping layout
. I tried look up other posts suggestion but still can’t solve the problem. Below are the codes I am working on:
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private static final String HI ="http://xxx/phpMyAdmin-5.0.4/Appi.php" ; //xxx is ip and the user name
private List<List_Data> list_data;
private RecyclerView rv;
private MyAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rv=(RecyclerView)findViewById(R.id.recyclerView);
rv.setHasFixedSize(true);
rv.setLayoutManager(new LinearLayoutManager(this));
list_data=new ArrayList<>();
adapter=new MyAdapter(list_data);
getMovieData();
}
private void getMovieData() {
StringRequest stringRequest=new StringRequest(Request.Method.GET, HI, new Response.Listener<String>() {
@Override
public void onResponse(String response) {
try {
JSONObject jsonObject=new JSONObject(response);
JSONArray array=jsonObject.getJSONArray("data");
for (int i=0; i<array.length(); i++ ){
JSONObject ob=array.getJSONObject(i);
List_Data listData=new List_Data(ob.getString("name")
,ob.getString("moive"));
list_data.add(listData);
}
rv.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
RequestQueue requestQueue= Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
}
The JSON format is:
[{"ID":"1","name":"ab","movie":"cd"},{"ID":"2","name":"ef","movie":"gh"}]
The adapter is:
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
private List<List_Data>list_data;
public MyAdapter(List<List_Data> list_data) {
this.list_data = list_data;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.list_data,parent,false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
List_Data listData=list_data.get(position);
holder.txtname.setText(listData.getName());
holder.txtmovie.setText(listData.getMoviename());
}
@Override
public int getItemCount() {
return list_data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView txtname,txtmovie;
public ViewHolder(View itemView) {
super(itemView);
txtname=(TextView)itemView.findViewById(R.id.txt_name);
txtmovie=(TextView)itemView.findViewById(R.id.txt_moviename);
}
}
}
Also, I setup the class like so:
public class List_Data {
private String name;
private String moviename;
public List_Data(String name, String moviename) {
this.name = name;
this.moviename = moviename;
}
public String getName() {
return name;
}
public String getMoviename() {
return moviename;
}
}
And the activity_main.xml is:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
And lis_data.xml:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<androidx.cardview.widget.CardView
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:padding="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:textColor="#111"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="name:"/>
<TextView
android:id="@+id/txt_name"
android:textColor="#111"
android:layout_marginLeft="10dp"
style="@style/Base.TextAppearance.AppCompat.Medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
<LinearLayout
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<LinearLayout
android:layout_marginLeft="10dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:textColor="#111"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="moivename:"/>
<TextView
android:id="@+id/txt_moviename"
android:textColor="#111"
android:layout_marginLeft="10dp"
style="@style/Base.TextAppearance.AppCompat.Medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
Thanks in advance for the suggestions!
3
Answers
Updates: I tried @hakim's suggestion. The app is still running but the data is not display.
I also found that
new Response.Listener<String>()
andnew Response.ErrorListener()
is greyed out in the getMoiveData() in the following:In your code, adapter will always re-set when new data obtained. It is better to set the adapter once and notify data change whenever new data obtained.
Here my suggestion.
on onCreate set recycler view adapter
in
getMovieData()
after data updated, calladapter.notifyDataSetChanged()
instead of set new adapterYou can used below code