I am developing sport news android app but when I run app it is showing white screen screenshot of emulator.
below my adapter class
public class ArticleAdapter extends RecyclerView.Adapter {
private List<Article> articles;
public ArticleAdapter(List<Article> articles, SportNews sportNews) {
this.articles = articles;
}
#NonNull
#Override
public CustomViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View itemView = (View) LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.article_list, null);
return new CustomViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull CustomViewHolder customViewHolder, int position) {
Article article = articles.get(position);
customViewHolder.articleAuthor.setText(article.getAuthor());
customViewHolder.articleTitle.setText(article.getTitle());
Picasso.get().load(article.getUrlToImage()).into(customViewHolder.articleImage);
}
#Override
public int getItemCount() {
if(articles == null) return 0;
return articles.size();
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.articleAuthor)
TextView articleAuthor;
#BindView(R.id.articleTitle)
TextView articleTitle;
#BindView(R.id.articleImage)
ImageView articleImage;
public CustomViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
}
}
}
below Retrofit interface class
public interface SportInterface {
#GET("/v2/top-headlines?sources=bbc-sport&apiKey=d03441ae1be44f9cad8c38a2fa6db215")
Call<SportNews> getArticles();
}
below retrofit client
public class SportClient {
private static final String ROOT_URL = "https://newsapi.org";
/**
* Get Retrofit Instance
*/
private static Retrofit getRetrofitInstance() {
return new Retrofit.Builder()
.baseUrl(ROOT_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
/**
* Get API Service
*
* #return API Service
*/
public static SportInterface getApiService() {
return getRetrofitInstance().create(SportInterface.class);
}
}
below MainActivity.java
public class MainActivity extends AppCompatActivity {
private SportNews sportNews;
private List<Article> articleList;
private ArticleAdapter articleAdapter;
#BindView(R.id.recyclerView)
RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
SportInterface sportInterface = SportClient.getApiService();
Call<SportNews> call = sportInterface.getArticles();
call.enqueue(new Callback<SportNews>() {
#Override
public void onResponse(Call<SportNews> call, Response<SportNews> response) {
sportNews = response.body();
articleAdapter = new ArticleAdapter( articleList, sportNews);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(articleAdapter);
}
#Override
public void onFailure(Call<SportNews> call, Throwable t) {
}
});
}
}
below Model SportNews class
public class SportNews {
#SerializedName("status")
#Expose
private String status;
#SerializedName("totalResults")
#Expose
private Integer totalResults;
#SerializedName("articles")
#Expose
private List<Article> articles = null;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public Integer getTotalResults() {
return totalResults;
}
public void setTotalResults(Integer totalResults) {
this.totalResults = totalResults;
}
public List<Article> getArticles() {
return articles;
}
public void setArticles(List<Article> articles) {
this.articles = articles;
}
}
below json response
{
"status": "ok",
"totalResults": 10,
"articles": [
{
"source": {
"id": "bbc-sport",
"name": "BBC Sport"
},
"author": "BBC Sport",
"title": "Gordon Taylor: PFA chief executive set to step down after 38 years",
"description": "Gordon Taylor to announce he will step down as chief executive of the Professional Footballers' Association (PFA) at the end of the season after 38 years.",
"url": "http://www.bbc.co.uk/sport/football/47691299",
"urlToImage": "https://ichef.bbci.co.uk/onesport/cps/624/cpsprodpb/13590/production/_97584297_breaking_news.png",
"publishedAt": "2019-03-27T13:04:18Z",
"content": "Gordon Taylor is set to announce he is standing down as chief executive of the Professional Footballers' Association after 38 years in the role.\r\nIt follows a mutiny from PFA chairman Ben Purkiss and former players over governance issues and controversy over … [+675 chars]"
},
]
}
Hi just copy paste below code because i have edited your MainActivity class where you forgot to add list from sportNews object that you can access in response of api calling.
public class MainActivity extends AppCompatActivity {
private SportNews sportNews;
private List<Article> articleList = new ArrayList<Article>();
private ArticleAdapter articleAdapter;
#BindView(R.id.recyclerView)
RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
SportInterface sportInterface = SportClient.getApiService();
Call<SportNews> call = sportInterface.getArticles();
call.enqueue(new Callback<SportNews>() {
#Override
public void onResponse(Call<SportNews> call, Response<SportNews> response) {
sportNews = response.body();
if(sportNews != null && sportNews.getArticles() != null){
articleList.addAll(sportNews.getArticles());
}
articleAdapter = new ArticleAdapter( articleList, sportNews);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(articleAdapter);
}
#Override
public void onFailure(Call<SportNews> call, Throwable t) {
}
});
}
}
your problem is in that line
articleAdapter = new ArticleAdapter( articleList, sportNews);
should be replaced with this
articleList=sportNews.getArticles();
articleAdapter = new ArticleAdapter( articleList, sportNews);
try this. i think your adapter is wrong.
public class ArticleAdapter extends RecyclerView.Adapter<ArticleAdapter.CustomViewHolder> {
Related
I'm a beginner programmer and I'm trying to receive data from the server using node.js and display the list on Android Studio but I keep having the following error:
E/RecyclerView: No adapter attached; skipping layout
D/HistoryActivity: HistoryResponse{result=[com.sooryong.loginexample.data.HistoryData#3303f3c, com.sooryong.loginexample.data.HistoryData#33764c5]}
D/AndroidRuntime: Shutting down VM
As you can see, I can't recall my list properly as well and I don't know how to fix it. Here are my codes:
public interface ServiceApi {
#POST("/user/login")
Call<LoginResponse> userLogin(#Body LoginData data);
#POST("/user/join")
Call<JoinResponse> userJoin(#Body JoinData data);
#GET("/test/history")
Call<HistoryResponse> getData();
}
HistoryData.java
public class HistoryData {
#SerializedName("eventID")
private int eventID;
#SerializedName("eventType")
private String eventType;
#SerializedName("eventDate")
private String eventDate;
#SerializedName("userID")
private int userID;
#SerializedName("sensorID")
private String sensorID;
public HistoryData(int eventID, String eventType, String eventDate, int userID, String sensorID) {
super();
this.eventID = eventID;
this.eventType = eventType;
this.eventDate = eventDate;
this.userID = userID;
this.sensorID = sensorID;
}
public int getEventID() {
return eventID;
}
public String getEventType() {
return eventType;
}
public String getEventDate() { return eventDate; }
public int getUserID() {
return userID;
}
public String getSensorID() { return sensorID; }
}
HistoryResponse.java
public class HistoryResponse {
#SerializedName("code")
public String code;
#SerializedName("message")
public String message;
#SerializedName("result")
public List<HistoryData> result;
#Override
public String toString() {
return "HistoryResponse{" + "result=" + result +'}';
}
}
HistoryActivity.java
public class HistoryActivity extends AppCompatActivity {
HistoryResponse dataList;
List<HistoryData> dataInfo;
private RecyclerView recyclerView;
private RecyclerAdapter recyclerAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recycler_view);
dataInfo = new ArrayList<>();
recyclerView = findViewById(R.id.recyclerView);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
ServiceApi apiInterface = RetrofitClient.getClient().create(ServiceApi.class);
Call<HistoryResponse> call = apiInterface.getData();
call.enqueue(new Callback<HistoryResponse>() {
#Override
public void onResponse(Call<HistoryResponse> call, Response<HistoryResponse> response) {
dataList = response.body();
Log.d("Response", dataList.toString());
dataInfo = dataList.result;
recyclerAdapter = new RecyclerAdapter(getApplicationContext(), dataInfo);
recyclerView.setAdapter(recyclerAdapter);
}
#Override
public void onFailure(Call<HistoryResponse> call, Throwable t) {
Log.d("Response", t.getMessage());
}
});
}
}
RecyclerAdapter.java
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder>{
private Context c;
private List<HistoryData> dataList;
public RecyclerAdapter(Context c, List<HistoryData> dataList) {
this.c = c;
this.dataList = dataList;
}
#NonNull
#Override
public RecyclerAdapter.MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(c).inflate(R.layout.recycler_view, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerAdapter.MyViewHolder holder, int position) {
holder.id.setText(dataList.get(position).getSensorID());
holder.type.setText("" + dataList.get(position).getEventType());
holder.date.setText("" + dataList.get(position).getEventDate());
}
#Override
public int getItemCount() {
return (dataList == null) ? 0 : dataList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView id;
TextView type;
TextView date;
public MyViewHolder(#NonNull View itemView) {
super(itemView);
id = (TextView)itemView.findViewById(R.id.sensorID);
type = (TextView)itemView.findViewById(R.id.eventType);
date = (TextView)itemView.findViewById(R.id.eventDate);
}
}
}
I don't think the data is being initialized properly inside the RecyclerAdapter class. Is it because I couldn't load the data properly from the server?
I ever face the same issue similiar to this.
What I've done was: initialize the adapter once only the activity created:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.recycler_view);
dataInfo = new ArrayList<>();
initAdapter();
....
}
private void initAdapter() {
//The adapter should create once in onCreate
recyclerView = findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext, LinearLayoutManager.VERTICAL, false);
recyclerAdapter = new RecyclerAdapter(getApplicationContext(), dataInfo);
recyclerView.setAdapter(recyclerAdapter);
}
Then when in callback result: you can clear the previous data before reload to the adapter:
call.enqueue(new Callback<HistoryResponse>() {
#Override
public void onResponse(Call<HistoryResponse> call, Response<HistoryResponse> response) {
dataList = response.body();
dataInfo.clear(); // <- here we clear all previous data before reload result to the adapter.
dataInfo = dataList.result;
recyclerAdapter.notifyDataSetChanged()
#Override
public void onFailure(Call<HistoryResponse> call, Throwable t) {
Log.d("Response", t.getMessage());
}
});
Hope this help.
API Json
{
"status": true,
"message": "Subjects found.",
"data": {
"subjects": [
{
"subj_id": "2",
"name": "Maths",
"img": "Math.jpg"
},
{
"subj_id": "1",
"name": "Physics",
"img": "physics.png"
}
],
"total": 2
}
}
GET Method
#GET(WebServices.GET_ACTIVE_SUBJECT)
Call<SubjectTopics> getSubjects();
Model Class
public class SubjectTopics
{
#SerializedName("status")
#Expose
private Boolean status;
#SerializedName("message")
#Expose
private String message;
#SerializedName("data")
#Expose
private Data data;
public Boolean getStatus() {
return status;
}
public void setStatus(Boolean status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
}
#SerializedName("subjects")
#Expose
private List<Subjects> subjects = null;
#SerializedName("total")
#Expose
private Integer total;
public List<Subjects> getSubjects() {
return subjects;
}
public void setSubjects(List<Subjects> subjects) {
this.subjects = subjects;
}
public Integer getTotal() {
return total;
}
public void setTotal(Integer total) {
this.total = total;
}
public class Subjects {
#SerializedName("subj_id")
#Expose
private String subjId;
#SerializedName("name")
#Expose
private String name;
#SerializedName("img")
#Expose
private String img;
public String getSubjId() {
return subjId;
}
public void setSubjId(String subjId) {
this.subjId = subjId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getImg() {
return img;
}
public void setImg(String img) {
this.img = img;
}
}
My Adapter Class
public class DataAdapter extend
RecyclerView.Adapter<DataAdapter.ViewHolder> {
private ArrayList<Subjects> android;
private Context context;
public DataAdapter(ArrayList<Subjects> android,Context context) {
this.android = android;
this.context = context;
}
#Override
public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.subject_topic_list_row,
viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(DataAdapter.ViewHolder viewHolder, final int position) {
viewHolder.subjectName.setText(android.get(position).getName());
viewHolder.relativeClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, SubjectTopicList.class);
intent.putExtra("subject_id", android.get(position).getSubjId());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
Picasso.with(context)
.load(android.get(position).getImg())
.placeholder(R.drawable.load)
.into(viewHolder.ImageV);
}
#Override
public int getItemCount() {
return android.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView subjectName;
private TextView ID;
private ImageView ImageV;
private RelativeLayout relativeClick;
public ViewHolder(View view) {
super(view);
subjectName = (TextView) itemView.findViewById(R.id.textView);
relativeClick = (RelativeLayout) itemView.findViewById(R.id.relative_click);
ImageV = (ImageView) itemView.findViewById(R.id.imageView);
}
}
}
Main Activity
private void initViews() {
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(UnitTestSubjects.this);
recyclerView.setLayoutManager(layoutManager);
if (NetworkUtils.isNetworkAvailableToastIfNot(getApplicationContext())) {
getSubjects();
}
}
private void getSubjects() {
progressBar.setVisibility(View.VISIBLE);
Call<SubjectTopics> getProductsModelClassCall = webService.getSubjects();
getProductsModelClassCall.enqueue(new Callback<SubjectTopics>() {
#Override
public void onResponse(Call<SubjectTopics> call, Response<Example> response) {
if (response.isSuccessful()) {
SubjectTopics jsonResponse = response.body();
list = new ArrayList<Subjects>(jsonResponse.getData().getSubjects());
adapter = new DataAdapter(list);
recyclerView.setAdapter(adapter);
} else {
APIError apiError = ErrorUtils.parseError(response);
Toast.makeText(UnitTestSubjects.this, ""+apiError, Toast.LENGTH_SHORT).show();
}
if (progressBar.isEnabled())
progressBar.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<Example> call, Throwable t) {
t.printStackTrace();
Toast.makeText(UnitTestSubjects.this, "Please Try Again", Toast.LENGTH_SHORT).show();
if (progressBar.isEnabled())
progressBar.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.GONE);
}
});
}
I am beginner in android Retrofit2 API call.
How to fetch items and set in recycler view .I think am not getting how to set items to the adapter class.
please help me out with this.
I have tried all possible ways to solve but not able to find any solution regarding this.
You have error with your models. They aren't properly configured. Please see this tutorial for a better understanding of retrofit and recyclerview.
Hi I'm building chat app UI with android but it runs without showing any data or views,
I interact with a bot server that should return text after I send a text. I'm using retrofit for http connections.
the model class showing are the response from json
please help me and ask me any details you want
My adapter
public class MessageListAdapter extends
RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int VIEW_TYPE_MESSAGE_SENT = 1;
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2;
private List<Messages> data;
private Context mContext;
// constructor
public MessageListAdapter(List<Messages> data, Context mContext) {
this.data = data;
this.mContext = mContext;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView;
if (viewType == VIEW_TYPE_MESSAGE_SENT) {
return new SentMessageHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.user_message, parent, false));
} else {
return new RecvdMessageHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.bot_message, parent, false));
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int type = getItemViewType(position);
Messages messages = data.get(position);
if (type == VIEW_TYPE_MESSAGE_SENT) {
SentMessageHolder sentMessageHolder = (SentMessageHolder) holder;
sentMessageHolder.messageBody.setText(messages.getText());
} else {
RecvdMessageHolder recvdMessageHolder = (RecvdMessageHolder) holder;
recvdMessageHolder.messageBody.setText(messages.getText());
}
}
public int getItemViewType(int position) {
Messages messages = data.get(position);
if (messages.getRecipientId() == ("default")) {
return VIEW_TYPE_MESSAGE_SENT;
} else
return VIEW_TYPE_MESSAGE_RECEIVED;
}
#Override
public int getItemCount() {
if (data != null) {
return data.size();
} else return 0;
}
class SentMessageHolder extends RecyclerView.ViewHolder {
public TextView messageBody;
public SentMessageHolder(View itemView) {
super(itemView);
messageBody = (TextView) itemView.findViewById(R.id.text_message_body);
}
}
class RecvdMessageHolder extends RecyclerView.ViewHolder {
public TextView messageBody;
public RecvdMessageHolder(View itemView) {
super(itemView);
messageBody = (TextView) itemView.findViewById(R.id.text_message_body);
}
}
My activity
public class MainActivity extends AppCompatActivity {
private EditText editText;
private RecyclerView mMessageRecycler;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter MessageListAdapter;
List<Messages> data;
//init client
Retrofit retrofit = RetrofitClient.getRetrofitClient();
//contact with the interface
APIService apiService = retrofit.create(APIService.class);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = findViewById(R.id.my_msg);
data = new ArrayList<>();
mMessageRecycler = (RecyclerView) findViewById(R.id.reyclerview_message_list);
MessageListAdapter = new MessageListAdapter(data , this);
// messageListAdapter.notifyDataSetChanged();
mMessageRecycler.setAdapter(MessageListAdapter);
mMessageRecycler.setLayoutManager(new LinearLayoutManager(this));
mMessageRecycler.setHasFixedSize(true);
}
public void clickedbtn(View view) {
fetchMessages();
}
private void fetchMessages() {
Call<List<Messages>> res = apiService.getBotResponse(editText.getText().toString());
res.enqueue(new Callback<List<Messages>>() {
#Override
public void onResponse(Call<List<Messages>> call, Response<List<Messages>> response) {
List<Messages> messages = response.body();
data.addAll(messages);//Changed here
MessageListAdapter.notifyDataSetChanged();//Changed here
mMessageRecycler.smoothScrollToPosition(messages.size()-1);
}
#Override
public void onFailure(Call<List<Messages>> call, Throwable t) {
}
});
}
My model class
public class Messages {
#SerializedName("recipient_id")
#Expose
private String recipientId;
#SerializedName("text")
#Expose
private String text;
public Messages(String text) {
this.text = text;
}
public String getRecipientId() {
return recipientId;
}
public void setRecipientId(String recipientId) {
this.recipientId = recipientId;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
Try adding both the instantiation of the Adapter and the RecyclerView.setAdapter() to the retrofit onResponse():
Like this:
Call<List<Messages>> res = apiService.getBotResponse(editText.getText().toString());
res.enqueue(new Callback<List<Messages>>() {
#Override
public void onResponse(Call<List<Messages>> call, Response<List<Messages>> response) {
List<Messages> messages = response.body();
//Init the Adpater here!!
MessageListAdapter = new MessageListAdapter(data , this);
//SetAdapter here!!
mMessageRecycler.setAdapter(MessageListAdapter);
data.addAll(messages);//Changed here
MessageListAdapter.notifyDataSetChanged();//Changed here
mMessageRecycler.smoothScrollToPosition(messages.size()-1);
}
#Override
public void onFailure(Call<List<Messages>> call, Throwable t) {
}
});
EDIT:
In addition to the above, your clickedbtn() should look like this:
public void clickedbtn(View view) {
Messages msg = new Messages(editText.getText().toString());
msg.setRecipientId("default");
data.add(msg);
MessageListAdapter.notifyDataSetChanged();
fetchMessages();
}
In my application I get some data from server and show into RecyslerView.
I can get data and fill adapter and show into RecyclerView, but I want write Test for this with Mockito Test and fill adapter for show into RecyclerView.
I use this link for json : https://api.learn2crack.com/android/jsonandroid/
I write below codes but I don't know how can I write Test for this.
My Activity class :
public class MainActivity extends AppCompatActivity {
private RecyclerView list;
private Context context;
private ApiServices apiServices;
private List<Android> model = new ArrayList<>();
private RecyclerAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
apiServices = ApiClient.getClient().create(ApiServices.class);
list = findViewById(R.id.list);
list.setLayoutManager(new LinearLayoutManager(context));
list.setHasFixedSize(true);
adapter = new RecyclerAdapter(model);
list.setAdapter(adapter);
Call<AndroidResponse> call = apiServices.getAndroid();
call.enqueue(new Callback<AndroidResponse>() {
#Override
public void onResponse(Call<AndroidResponse> call, Response<AndroidResponse> response) {
if (response.isSuccessful()) {
if (response.body() != null) {
model.clear();
model.addAll(response.body().getAndroid());
adapter.notifyDataSetChanged();
}
}
}
#Override
public void onFailure(Call<AndroidResponse> call, Throwable t) {
}
});
}
}
My Adapter class :
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private List<Android> model;
public RecyclerAdapter(List<Android> model) {
this.model = model;
}
#NonNull
#Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row_list, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull RecyclerAdapter.ViewHolder holder, int position) {
holder.name.setText(model.get(position).getName());
holder.version.setText(model.get(position).getVer());
holder.api.setText(model.get(position).getApi());
}
#Override
public int getItemCount() {
return model.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView name, version, api;
public ViewHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.rowName);
version = itemView.findViewById(R.id.rowVersion);
api = itemView.findViewById(R.id.rowApi);
}
}
}
My Test class :
#LargeTest
#RunWith(AndroidJUnit4.class)
public class MainActivityTest extends InstrumentationTestCase {
#Rule
public ActivityTestRule<MainActivity> mainActivityTestRule = new ActivityTestRule<>(MainActivity.class, true, false);
private MockWebServer mockWebServer;
#Before
public void setUp() throws Exception {
super.setUp();
mockWebServer = new MockWebServer();
mockWebServer.start();
injectInstrumentation(InstrumentationRegistry.getInstrumentation());
AppConstants.BASE_URL = mockWebServer.url("/").toString();
}
#Test
public void setupAndroidListAdapterTest() throws Exception {
String fileName = "android_list_response.json";
mockWebServer.enqueue(new MockResponse()
.setResponseCode(200)
.setBody(fileName));
Intent intent = new Intent();
mainActivityTestRule.launchActivity(intent);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#After
public void tearDown() throws Exception {
mockWebServer.shutdown();
}
}
I saved above json into asset folder.
I write above codes and when run test show me 1 test pass but not show me any data into recyclerView and adapter!
How can I do it?
Hi I am not sure why exactly my recycler view is not displaying but I get the following error even after initializing it on onCreate method as mentioned by other SO users who faced the same problem:
E/RecyclerView: No adapter attached; skipping layout
Also maybe Retrofit is not able to get the data so onResponse is never called hence onFailure is called. I am using an online JSON API. Link:
https://reqres.in/api/users?page=1&per_page=3
ApiClient.java
public class ApiClient {
public static final String BASE_URL = "https://reqres.in/api/";
public static Retrofit retrofit = null;
public static Retrofit getApiClient(){
if(retrofit == null){
retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}}
DataResponse.java
public class DataResponse {
#SerializedName("page")
private int page;
#SerializedName("per_page")
private int per_page;
#SerializedName("total")
private int total;
#SerializedName("total_pages")
private int total_pages;
#SerializedName("data")
List<Data> data;
public int getPage() {
return page;
}
public int getPer_page() {
return per_page;
}
public int getTotal() {
return total;
}
public int getTotal_pages() {
return total_pages;
}
public List<Data> getData() {
return data;
}
}
class Data {
#SerializedName("id")
private int id;
#SerializedName("first_name")
private String first_name;
#SerializedName("last_name")
private String last_name;
#SerializedName("avatar")
private String avatar;
public int getId() {
return id;
}
public String getFirst_name() {
return first_name;
}
public String getLast_name() {
return last_name;
}
public String getAvatar() {
return avatar;
}
}
ApiInterface
public interface ApiInterface {
#GET("users")
Call<List<DataResponse>> getUsers(#Query("page") int page, #Query("per_page") int per_page);}
RecyclerAdapter.java
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.MyViewHolder> {
private List<Data> dataList;
private Context context;
public RecyclerAdapter(List<Data> dataList, Context context){
this.dataList = dataList;
this.context = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout, parent, false);
return new MyViewHolder(view);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Data data = dataList.get(position);
holder.fullname.setText(data.getFirst_name() + ", " + data.getLast_name());
Glide.with(context).load(data.getAvatar()).into(holder.avatar);
}
#Override
public int getItemCount() {
return dataList.size();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
ImageView avatar;
TextView fullname;
public MyViewHolder(View itemView) {
super(itemView);
avatar = (ImageView) itemView.findViewById(R.id.cardView_image);
fullname = (TextView) itemView.findViewById(R.id.cardView_location);
}
}
public void addData(List<Data> data){
for(Data d: data){
dataList.add(d);
}
}}
MainActivity
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private ProgressBar progressBar;
private GridLayoutManager layoutManager;
private RecyclerAdapter adapter;
private ApiInterface apiInterface;
private int page_num = 1;
private int per_page = 3;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = null;
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
layoutManager = new GridLayoutManager(this, 2);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setVisibility(View.VISIBLE);
Call<List<DataResponse>> call = apiInterface.getUsers(page_num, per_page);
call.enqueue(new Callback<List<DataResponse>>() {
#Override
public void onResponse(Call<List<DataResponse>> call, Response<List<DataResponse>> response) {
Toast.makeText(MainActivity.this, "Response success....", Toast.LENGTH_SHORT).show();
List<Data> data = response.body().get(1).getData();
adapter = new RecyclerAdapter(data, MainActivity.this);
recyclerView.setAdapter(adapter);
Toast.makeText(MainActivity.this, "First page is loaded...", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<List<DataResponse>> call, Throwable t) {
Toast.makeText(MainActivity.this, "Bad request", Toast.LENGTH_SHORT).show();
}
});
}}
Would highly appreciate any help, thank you.
You are making an array request, convert it to object request(your api endpoint is returning json object). Change the call like this
Call<DataResponse> call = apiInterface.getUsers(page_num, per_page);
call.enqueue(new Callback<DataResponse>() {
#Override
public void onResponse(Call<DataResponse> call, Response<DataResponse> response) {
Toast.makeText(MainActivity.this, "Response success....", Toast.LENGTH_SHORT).show();
List<Data> data = response.body().getData();
adapter = new RecyclerAdapter(data, MainActivity.this);
recyclerView.setAdapter(adapter);
Toast.makeText(MainActivity.this, "First page is loaded...", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<DataResponse> call, Throwable t) {
Toast.makeText(MainActivity.this, "Bad request", Toast.LENGTH_SHORT).show();
}
});
and api interface should be like this
public interface ApiInterface {
#GET("users")
Call<DataResponse> getUsers(#Query("page") int page,
#Query("per_page") int per_page);
}
Its happen because you request is failed and you are not set adapter for recycler view change it
public class MainActivity extends AppCompatActivity {
private RecyclerView recyclerView;`
private ProgressBar progressBar;
private GridLayoutManager layoutManager;
private RecyclerAdapter adapter;
private ApiInterface apiInterface;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter = null;
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
layoutManager = new GridLayoutManager(this, 2);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
adapter = new RecyclerAdapter(data, MainActivity.this);
recyclerView.setAdapter(adapter);
apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setVisibility(View.VISIBLE);
Call<List<DataResponse>> call = apiInterface.getUsers(page_num, per_page);
call.enqueue(new Callback<List<DataResponse>>() {
#Override
public void onResponse(Call<List<DataResponse>> call, Response<List<DataResponse>> response) {
Toast.makeText(MainActivity.this, "Response success....", Toast.LENGTH_SHORT).show();
List<Data> data = response.body().get(1).getData();
adapter.notifydatasetchanged()
Toast.makeText(MainActivity.this, "First page is loaded...", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<List<DataResponse>> call, Throwable t) {
Toast.makeText(MainActivity.this, "Bad request", Toast.LENGTH_SHORT).show();
}
});
}