I am trying to use Retrofit2 to retrieve data as JSON and then parsing it to my RecyclerView adapter, but whatever I do I can't figure out how to get this thing to work.
At the moment, I can load up one RecyclerView with local DBFlow data, but can't figure out how to do it for the JSON that I HTTP GET with Retrofit2 for my second RecyclerView. I have the code below so far, which loads the JSON in the Log. But can't parse it to the RecyclerView.
MainActivity.java:
onCreate() {
...
mGithubApi = ApiUtils.getApi();
mGithubRecyclerView = (RecyclerView)
findViewById(R.id.github_repository_recyclerview);
RecyclerView.LayoutManager mGithubLayoutManager = new
LinearLayoutManager(getApplicationContext());
mGithubRecyclerView.setLayoutManager(mGithubLayoutManager);
mGithubRecyclerView.setHasFixedSize(true);
...
loadGithubUserRepositoryJson();
}
// Load Github repo JSON
public void loadGithubUserRepositoryJson() {
Call<ResponseBody> result = api.getRepos("motivecodex");
result.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
Log.e(LOG_TAG, response.body().string());
mGithubAdapter = new GithubRepositoriesAdapter((List<GithubRepository>) mGithubRepository);
mGithubRecyclerView.setAdapter(mGithubAdapter);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.e("MainActivity", "error loading from API");
}
});
}
GithubRepositoryAdapter.java
public class GithubRepositoriesAdapter extends RecyclerView.Adapter<GithubRepositoriesAdapter.RepositoryViewHolder> {
private List<GithubRepository> githubRepositoryList;
public class RepositoryViewHolder extends RecyclerView.ViewHolder {
public TextView repository, commits, stars, forks;
public RepositoryViewHolder(View view) {
super(view);
repository = (TextView) view.findViewById(R.id.listitem_repository);
commits = (TextView) view.findViewById(R.id.listitem_commits);
stars = (TextView) view.findViewById(R.id.listitem_stars);
forks = (TextView) view.findViewById(R.id.listitem_forked);
}
}
public GithubRepositoriesAdapter(List<GithubRepository> githubRepositoryList) {
this.githubRepositoryList = githubRepositoryList;
}
#Override
public RepositoryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.listitem_repository, parent, false);
return new RepositoryViewHolder(itemView);
}
#Override
public void onBindViewHolder(RepositoryViewHolder holder, int position) {
GithubRepository githubRepository = githubRepositoryList.get(position);
holder.repository.setText(githubRepository.getName());
holder.commits.setText(githubRepository.getStargazersCount());
holder.stars.setText(githubRepository.getStargazersCount());
holder.forks.setText(githubRepository.getForks());
}
#Override
public int getItemCount() {
return githubRepositoryList.size();
}
}
interface Api.java:
#GET("users/{user}/repos")
Call<List<GithubRepository>> listRepos(#Path("user") String user);
model GithubRepository.java
public class GithubRepository {
#SerializedName("id")
#Expose
private Integer id;
#SerializedName("name")
#Expose
private String name;
#SerializedName("full_name")
#Expose
private String fullName;
#SerializedName("stargazers_count")
#Expose
private Integer stargazersCount;
#SerializedName("forks")
#Expose
private Integer forks;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public Integer getStargazersCount() {
return stargazersCount;
}
public void setStargazersCount(Integer stargazersCount) {
this.stargazersCount = stargazersCount;
}
public Integer getForks() {
return forks;
}
public void setForks(Integer forks) {
this.forks = forks;
}
}
ApiUtil.java
public static final String BASE_URL = "https://api.github.com/users/";
public static Api getApi() {
return RetrofitClient.getClient(BASE_URL).create(Api.class);
}
RetrofitClient.java
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
Instead of Log (this approximately as I can't see your types):
localRepositoryList.addAll(response.body());
adapter.notifyDataSetChanged();
P.S: I assume you have in the code something like:
GithubRepositoriesAdapter adapter=new GithubRepositoriesAdapter(localRepositoryList);
mGithubRecyclerView.setAdapter(adapter);
Another option in log place:
mGithubRecyclerView.setAdapter(new GithubRepositoriesAdapter(response.body()));
UPDATE:
public void loadGithubUserRepositoryJson() {
api.listRepos("motivecodex").enqueue(new Callback<List<GithubRepository>>() {
#Override
public void onResponse(Call<List<GithubRepository>> call, Response<List<GithubRepository>> response) {
try {
Log.e(LOG_TAG, response.body().string());
mGithubAdapter = new GithubRepositoriesAdapter(response.body());
mGithubRecyclerView.setAdapter(mGithubAdapter);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<List<GithubRepository>> call, Throwable t) {
Log.e("MainActivity", "error loading from API");
}
});
}
Related
I am again trying to use TMBD api. I am using a recyclerview to map the data into a list.But the response I am getting from the retrofit response is null.
Main Activity:
public class MainActivity extends AppCompatActivity {
public final static String BASE_URL="https://api.themoviedb.org";
public final static String apiKey="<ApiKey>";
public final static String language="en-US";
public final static String TAG="tag";
#BindView(R.id.recyclerView)
RecyclerView movieList;
DisplayAdapter adapter;
MovieResponse result;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface apiInterface=retrofit.create(ApiInterface.class);
apiInterface.getMovies(apiKey,language,1)
.enqueue(new Callback<MovieResponse>() {
#Override
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
if(response.isSuccessful())
{
result=response.body();
Log.e(TAG, "onCreate: "+result );
}
}
#Override
public void onFailure(Call<MovieResponse> call, Throwable t) { }
});
Log.e(TAG, "onCreate: "+result );
adapter=new DisplayAdapter(getApplicationContext(),result);
RecyclerView.LayoutManager layoutManager=new GridLayoutManager(getApplicationContext(),1);
movieList.setLayoutManager(layoutManager);
movieList.setAdapter(adapter);
}
}
Response Class:
public class MovieResponse {
private int page;
private int total_results;
private int total_pages;
private List<ResultsBean> results;
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getTotal_results() {
return total_results;
}
public void setTotal_results(int total_results) {
this.total_results = total_results;
}
public int getTotal_pages() {
return total_pages;
}
public void setTotal_pages(int total_pages) {
this.total_pages = total_pages;
}
public List<ResultsBean> getResults() {
return results;
}
public void setResults(List<ResultsBean> results) {
this.results = results;
}
public static class ResultsBean {
private double popularity;
private int vote_count;
private boolean video;
private String poster_path;
private int id;
private boolean adult;
private String backdrop_path;
private String original_language;
private String original_title;
private String title;
private double vote_average;
private String overview;
private String release_date;
private List<Integer> genre_ids;
public double getPopularity() {
return popularity;
}
public void setPopularity(double popularity) {
this.popularity = popularity;
}
public int getVote_count() {
return vote_count;
}
public void setVote_count(int vote_count) {
this.vote_count = vote_count;
}
public boolean isVideo() {
return video;
}
public void setVideo(boolean video) {
this.video = video;
}
public String getPoster_path() {
return poster_path;
}
public void setPoster_path(String poster_path) {
this.poster_path = poster_path;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isAdult() {
return adult;
}
public void setAdult(boolean adult) {
this.adult = adult;
}
public String getBackdrop_path() {
return backdrop_path;
}
public void setBackdrop_path(String backdrop_path) {
this.backdrop_path = backdrop_path;
}
public String getOriginal_language() {
return original_language;
}
public void setOriginal_language(String original_language) {
this.original_language = original_language;
}
public String getOriginal_title() {
return original_title;
}
public void setOriginal_title(String original_title) {
this.original_title = original_title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public double getVote_average() {
return vote_average;
}
public void setVote_average(double vote_average) {
this.vote_average = vote_average;
}
public String getOverview() {
return overview;
}
public void setOverview(String overview) {
this.overview = overview;
}
public String getRelease_date() {
return release_date;
}
public void setRelease_date(String release_date) {
this.release_date = release_date;
}
public List<Integer> getGenre_ids() {
return genre_ids;
}
public void setGenre_ids(List<Integer> genre_ids) {
this.genre_ids = genre_ids;
}
}
}
The Api Interface:
public interface ApiInterface {
#GET("3/movie/popular")
Call<MovieResponse> getMovies(
#Query("api_key") String apiKey,
#Query("language")String language,
#Query("page")int page
);
}
I am learning the concept of api calling. I dont understand why the response is null. If anybody could explai the reason it will be very helpfull.
This can be several things from what you posted.
It can be that the Java models don't match the JSON. You'd have to double check this.
It can be that you're getting an error, in which case retrofit does not have a response.body(), but rather a response.errorBody(). You can check this by debugging and checking response.erroeBody().string().
Or it could to be a classic example of asynch behaviour being handled like it's synchronous.
adapter=new DisplayAdapter(getApplicationContext(),result);
In this case you're using result, but it's assigned inside the retrofit callback which most likely finished after you create the adapter and hence result is still null.
You can move the creation of the adapter and setting it to the list inside the callback:
public void onResponse(Call<MovieResponse> call, Response<MovieResponse> response) {
if(response.isSuccessful())
{
result=response.body();
Log.e(TAG, "onCreate: "+result );
adapter=new DisplayAdapter(getApplicationContext(),result);
RecyclerView.LayoutManager layoutManager=new GridLayoutManager(getApplicationContext(),1);
movieList.setLayoutManager(layoutManager);
movieList.setAdapter(adapter);
}
}
These are the only things that come to mind. Hope it helps.
EDIT
After taking a look at the github project, the only thing I found that is crashing the app is inside DisplayAdapter.java line 44:
holder.movieRating.setText((int) listOfMovies.getResults().get(position).getVote_average());
When you call setText that accepts an int you are in fact calling a method that will look in your strings.xml for a string with the id equal to the int you passed in. In this case, you are passing the vote average as an int. I'm guessing that what you want is to display the vote average, so the solution is to convert the double vote average to a string. This can easily be achieved with String.valueOf:
holder.movieRating.setText(String.valueOf(listOfMovies.getResults().get(position).getVote_average()));
Perhaps the most interesting bit is in the log message android.content.res.Resources$NotFoundException: String resource ID #0x7. This is thrown when trying to look for the string that doesn't exist.
I am new to retrofit 2 and i am trying to get json array data but getting null, this is the url for getting the data.
But the funny thing is when i try to debug inside onResponse i am getting success message as well as response.body data. What is the problem here?
https://xenzet.com/GameCheat/viewgamesjson.php
this is json data
[
{
"gameid":"2",
"gameIcon":"https:\/\/xenzet.com\/GameCheat\/uploads\/counter strike 1.6.png",
"Games_Name":"1"
},
{
"gameid":"3",
"gameIcon":"https:\/\/xenzet.com\/GameCheat\/uploads\/gta.ico",
"Games_Name":"vice city sucjlfsdrgefdsrhag"
},
{
"gameid":"4",
"gameIcon":"https:\/\/xenzet.com\/GameCheat\/uploads\/pubg.png",
"Games_Name":"pubg"
},
{
"gameid":"5",
"gameIcon":"https:\/\/xenzet.com\/GameCheat\/uploads\/doom.png",
"Games_Name":"Doom Enternal"
},
{
"gameid":"6",
"gameIcon":"https:\/\/xenzet.com\/GameCheat\/uploads\/for.png",
"Games_Name":"Fornite"
},
{
"gameid":"9",
"gameIcon":"https:\/\/xenzet.com\/GameCheat\/uploads\/dota2.png",
"Games_Name":"dota2"
}
]
this is the method which is trying to get data
public void fetch_information() {
ApiInterface = ApiClient.getApiClient().create(Api.class);
Call<List<Games>> call = ApiInterface.GetGames();
call.enqueue(new Callback<List<Games>>() {
#Override
public void onResponse(Call<List<Games>> call, Response<List<Games>> response) {
if(response.isSuccessful()) {
gameslist = response.body();
gamescounter = gameslist.size();
adapter = new GameRecyclerViewAdapter(GamesActivity.this, gameslist);
recyclerView.setAdapter(adapter);
}
}
#Override
public void onFailure(Call<List<Games>> call, Throwable t) {
Toast.makeText(getApplicationContext(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
this is ApiClient
public class ApiClient {
public static String Base_URL ;
public static Retrofit retrofit;
public static Retrofit getApiClient()
{
if (retrofit == null)
{
Base_URL ="https://xenzet.com/GameCheat/";
retrofit = new Retrofit.Builder().baseUrl(Base_URL)
.addConverterFactory(GsonConverterFactory.create()).build();
}
return retrofit;
}
}
and Api
public interface Api {
#GET("viewgamesjson.php")
Call<List<Games>> GetGames();
}
and in OnCreate i am calling fetch information method.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_games);
gameslist = new ArrayList<Games>();
RecyclerView recyclerView = findViewById(R.id.recyclerview_gameslist);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
fetch_information();
Toast.makeText(getApplicationContext(),"" +gamescounter, Toast.LENGTH_SHORT).show();
adapter = new GameRecyclerViewAdapter(this, gameslist);
recyclerView.setAdapter(adapter);
adapter.setClickListener((GameRecyclerViewAdapter.ItemClickListener) this);
}
trying to fill data of game list in recycler view but fails as it null.
this is logcat
2019-05-27 14:03:43.261 1261-1261/com.example.quizgames E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.quizgames, PID: 1261
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setAdapter(android.support.v7.widget.RecyclerView$Adapter)' on a null object reference
at com.example.quizgames.GamesActivity$1.onResponse(GamesActivity.java:109)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:70)
at android.os.Handler.handleCallback(Handler.java:836)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6251)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
This is class Games
public class Games {
#SerializedName("gameid")
#Expose
private String gameid;
#SerializedName("gameIcon")
#Expose
private String gameIcon;
#SerializedName("Games_Name")
#Expose
private String gamesName;
public String getGameid() {
return gameid;
}
public void setGameid(String gameid) {
this.gameid = gameid;
}
public String getGameIcon() {
return gameIcon;
}
public void setGameIcon(String gameIcon) {
this.gameIcon = gameIcon;
}
public String getGamesName() {
return gamesName;
}
public void setGamesName(String gamesName) {
this.gamesName = gamesName;
}
// public Games(String Gameid,String Gameicon,String GameName)
// {
// this.gameid = Gameid;
// this.gameIcon = Gameicon;
// this.gamesName = GameName;
//
// }
}
This is recycler view
class GameRecyclerViewAdapter extends RecyclerView.Adapter<GameRecyclerViewAdapter.ViewHolder> {
private List<Games> mGames;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
GameRecyclerViewAdapter(Context context, List<Games> games) {
this.mInflater = LayoutInflater.from(context);
this.mGames = games;
}
// inflates the row layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.gameitem, parent, false);
return new ViewHolder(view);
}
// binds the data to the TextView in each row
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Games Game = mGames.get(position);
String Gameid = Game.getGameid();
String Gameicon = Game.getGameIcon();
String Gamename = Game.getGamesName();
holder.GameNameTxt.setText(Gamename);
Glide.with(holder.GameIconImage.getContext()).load(Game.getGameIcon()).thumbnail(0.1f).
placeholder(R.color.colorPrimary).diskCacheStrategy(DiskCacheStrategy.NONE).into(holder.GameIconImage);
}
// total number of rows
#Override
public int getItemCount() {
return mGames == null ? 0 : mGames.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView GameNameTxt;
ImageView GameIconImage;
ViewHolder(View itemView) {
super(itemView);
GameNameTxt = itemView.findViewById(R.id.gamename);
GameIconImage = itemView.findViewById(R.id.imageView);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
// allows clicks events to be caught
void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
}
Add data in your Adapter in side onResponse Method
add fetch_information() in oncreate
#Override
public void onResponse(Call<List<Games>> call, Response<List<Games>> response) {
if(response.isSuccessful()) {
gameslist = response.body();
adapter = new GameRecyclerViewAdapter(MainActivity.this, gameslist);
//change your Activity name here insted of MainActivity
recyclerView.setAdapter(adapter);
}
}
I didn't check where you make mistake. But this code implementation returning me list having 10 data inside list.
public interface APIInterface {
#GET()
Call<List<ViewGame>> viewgamesjson(#Url String url);
}
This is model class:
public class ViewGame {
String gameid,gameIcon,Games_Name;
public String getGameid() {
return gameid;
}
public void setGameid(String gameid) {
this.gameid = gameid;
}
public String getGameIcon() {
return gameIcon;
}
public void setGameIcon(String gameIcon) {
this.gameIcon = gameIcon;
}
public String getGames_Name() {
return Games_Name;
}
public void setGames_Name(String games_Name) {
Games_Name = games_Name;
}
}
This is APiClient Class:
public class APIClient {
static Retrofit retrofit = null;
public static String Base_URL = "https://xenzet.com/GameCheat/";
public static APIInterface getInterface() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder()
.readTimeout(60, TimeUnit.SECONDS)
.connectTimeout(60, TimeUnit.SECONDS)
.addInterceptor(interceptor)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(Base_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit.create(APIInterface.class);
}
}
And this is API Call:
private void viewGame() {
Call<List<ViewGame>> call = APIClient.getInterface().viewgamesjson("https://xenzet.com/GameCheat/viewgamesjson.php");
call.enqueue(new Callback<List<ViewGame>>() {
#Override
public void onResponse(Call<List<ViewGame>> call, Response<List<ViewGame>> response) {
try {
Global.dismissProgress();
if (response.isSuccessful() && response.body() != null) {
Global.dismissProgress();
Global.printLog("size===", response.body().size() + "");
} else {
Global.dismissProgress();
}
} catch (Exception e) {
e.printStackTrace();
Global.dismissProgress();
}
}
#Override
public void onFailure(Call<List<ViewGame>> call, Throwable t) {
Global.dismissProgress();
try {
Global.showToast(SplashActivity.this, getString(R.string.something_wrong));
} catch (Exception e) {
e.printStackTrace();
}
call.cancel();
t.printStackTrace();
}
});
}
The problem is, that you set up your list adapter in onCreate(), where gameslist is still null.
adapter = new GameRecyclerViewAdapter(this, gameslist);
recyclerView.setAdapter(adapter);
When you call the setAdapter() method, the recyclerView will ask the adapter for the number of items; and in getItemCount() I suppose, you have something like return gameslist.count(). Since gameslist is still null, this causes the NPE.
To fix it, change getItemCount() to something like this:
return gameslist == null ? 0 : gameslist.size()
EDIT
I checked your URL (with Postman), and it appears that the content-type of the response is text/html and not application/json as it should be. I suppose that therefore the response isn't converted using Gson and thus you end up with null.
API File
METHOD : GET
OUTPUT:
{
"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
}
}
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;
}
}
public class 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
public class MoviesAdapter extends RecyclerView.Adapter<MoviesAdapter.MovieViewHolder> {
private List<Subjects> movies;
private int rowLayout;
private Context context;
public static class MovieViewHolder extends RecyclerView.ViewHolder {
private TextView subjectName;
private TextView ID;
private ImageView ImageV;
private RelativeLayout relativeClick;
public MovieViewHolder(View v) {
super(v);
subjectName = (TextView) itemView.findViewById(R.id.textView);
relativeClick = (RelativeLayout) itemView.findViewById(R.id.relative_click);
ImageV = (ImageView) itemView.findViewById(R.id.imageView);
}
}
public MoviesAdapter(List<Subjects> movies, int rowLayout, Context context) {
this.movies = movies;
this.rowLayout = rowLayout;
this.context = context;
}
#Override
public MoviesAdapter.MovieViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);
return new MoviesAdapter.MovieViewHolder(view);
}
#Override
public void onBindViewHolder(MoviesAdapter.MovieViewHolder holder, final int position) {
holder.subjectName.setText(movies.get(position).getName());
holder.relativeClick.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, SubjectTopicList.class);
intent.putExtra("subject_id", movies.get(position).getSubjId());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
});
Picasso.with(context)
.load(movies.get(position).getImg())
.placeholder(R.drawable.load)
.into(holder.ImageV);
}
#Override
public int getItemCount() {
return movies.size();
}
}
Activity
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<SubjectTopics> response) {
if (response.isSuccessful()) {
List<Subjects> movies = response.body().getData().getSubjects();
MoviesAdapter newAd=new MoviesAdapter(movies, R.layout.unit_test_row, getApplicationContext());
recyclerView.setAdapter(newAd);
} 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<SubjectTopics> call, Throwable t) {
Toast.makeText(UnitTestSubjects.this, "Please Try Again", Toast.LENGTH_SHORT).show();
if (progressBar.isEnabled())
progressBar.setVisibility(View.INVISIBLE);
progressBar.setVisibility(View.GONE);
}
});
}
Retrofit Code
public class ServiceGenerator {
private final static String TAG = "ApiCall";
public static Retrofit getRetrofit(){
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
// set your desired log level
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
// add your other interceptors …
// add logging as last interceptor
httpClient.addInterceptor(logging); // <-- this is the important line!
httpClient.connectTimeout(10, TimeUnit.SECONDS).readTimeout(14, TimeUnit.SECONDS).writeTimeout(16, TimeUnit.SECONDS);
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.create();
return new Retrofit.Builder()
.baseUrl(WebServices.BASE_URL)
.client(httpClient.build())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
public static Api getApi(){
return getRetrofit().create(Api.class);
}
}
After calling API's using Retrofit 2.0, Unable to get any response and getting this error:
Failure:
retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall#5321
every-time after callback it directly coming out from the method
I have tried all possible ways to solve but not able to find any solution regarding this.
I think this is internal retrofit error or in the pojo class I guess. Please help!
I'm trying to use blog id to get JSON object from server. At the moment I'm getting this error
java.lang.NullPointerException: Attempt to invoke interface method 'java.util.Iterator java.util.List.iterator()
on a null object reference`.How do I use the post Id to get the full content what am I doing wrong. Please help!!!
MyBlog Adapter:
public class MyBlogAdapter extends RecyclerView.Adapter<BlogViewHolder> {
List<BlogResponse> postsList;
Context context;
public static String blog_Id, blogID;
private LayoutInflater inflater;
public MyBlogAdapter(Context context, List<BlogResponse> postsList){
this.context = context;
this.inflater = LayoutInflater.from(context);
this.postsList = postsList;
}
#Override
public BlogViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(R.layout.custom_view,parent, false);
return new BlogViewHolder(view);
}
#Override
public void onBindViewHolder(BlogViewHolder holder, int position) {
final BlogResponse posts= postsList.get(position);
holder.summary.setText(posts.getBlogExcerpt().trim().toString());
holder.title.setText(posts.getBlogTitle().trim().toString());
// Glide.with(context).load(posts.getBlogThumbnail()).into(holder.cover);
holder.blogHolder.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, AnotherSingleView.class);
blog_Id = posts.getBlogId();
intent.putExtra(blogID,blog_Id);
Log.d("MyblogAdapter","Please check blog Id: "+blog_Id);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
Log.d("MyBlogAdapter,","getItemCount"+postsList.size());
return postsList == null ? (0) : postsList.size();
}
}
SecondActivity:
public class AnotherSingleView extends AppCompatActivity {
String postID;
int position;
public TextView blogTitle,blogSub,blogContent;
public ImageView blogPic;
List<SingleBlogPost> singleBlogPosts;
SingleBlogPost singleBlogPost;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_another_single_view);
Intent intent = getIntent();
Bundle showBlogId = intent.getExtras();
postID = showBlogId.getString(blogID);
Log.d("AnotherSingleView","Please check blog Id: "+postID);
singleBlogPosts = new ArrayList<>();
blogContent = (TextView)findViewById(R.id.blog_content);
blogSub = (TextView) findViewById(R.id.blog_subtitle);
blogTitle =(TextView) findViewById(R.id.blog_title);
blogPic =(ImageView) findViewById(R.id.blog_pix);
singlePostDisplay();
}
private void singlePostDisplay() {
BlogaPI api = ApiClient.getBlogInterface();
Call<List<SingleBlogPost>> call = api.postResponse(postID);
call.enqueue(new Callback<List<SingleBlogPost>>() {
#Override
public void onResponse(Call<List<SingleBlogPost>> call, Response<List<SingleBlogPost>> response) {
singleBlogPosts = response.body();
if (singleBlogPosts != null && !singleBlogPosts.isEmpty() ){
for (SingleBlogPost posts : singleBlogPosts){
Log.d("AnotherSingleView","Please check RESPONSE: "+response.body().toString());
blogTitle.setText(posts.getBlogTitle());
blogSub.setText(posts.getBlogSubtitle());
blogContent.setText(posts.getBlogContent());
// Glide.with(AnotherSingleView.this).load(singlepost.getBlogMedimg()).into(blogPic);
}
}
else{
Toast.makeText(AnotherSingleView.this, "Something is empty", Toast.LENGTH_SHORT).show();
} }
#Override
public void onFailure(Call<List<SingleBlogPost>> call, Throwable t) {
Toast.makeText(AnotherSingleView.this, "check again: "+t.toString(), Toast.LENGTH_SHORT).show();
}
});
}
}
Interface:
public interface BlogaPI {
#GET("blog")
Call<BlogList> response();
#GET("post/{blog_id}")
Call<List<SingleBlogPost>> postResponse(#Path("blog_id") String blog_id);
//Call<List<SingleBlogPost>> postResponse();
}
SingleBlogPost:
public class SingleBlogPost {
#SerializedName("blog_id")
#Expose
private String blogId;
#SerializedName("blog_title")
#Expose
private String blogTitle;
#SerializedName("blog_subtitle")
#Expose
private String blogSubtitle;
#SerializedName("blog_excerpt")
#Expose
private String blogExcerpt;
#SerializedName("blog_content")
#Expose
private String blogContent;
#SerializedName("blog_thumbnail")
#Expose
private String blogThumbnail;
#SerializedName("blog_medimg")
#Expose
private String blogMedimg;
#SerializedName("category_title")
#Expose
private String categoryTitle;
public SingleBlogPost(String blogId,String blogTitle, String blogSubtitle, String blogExcerpt,
String blogContent, String blogThumbnail, String blogMedimg, String categoryTitle){
this.blogId = blogId;
this.blogTitle = blogTitle;
this.blogSubtitle = blogSubtitle;
this.blogExcerpt = blogExcerpt;
this.blogContent = blogContent;
this.blogThumbnail = blogThumbnail;
this.blogMedimg = blogMedimg;
this.categoryTitle = categoryTitle;
}
public String getBlogId() {
return blogId;
}
public void setBlogId(String blogId) {
this.blogId = blogId;
}
public String getBlogTitle() {
return blogTitle;
}
public void setBlogTitle(String blogTitle) {
this.blogTitle = blogTitle;
}
public String getBlogSubtitle() {
return blogSubtitle;
}
public void setBlogSubtitle(String blogSubtitle) {
this.blogSubtitle = blogSubtitle;
}
public String getBlogExcerpt() {
return blogExcerpt;
}
public void setBlogExcerpt(String blogExcerpt) {
this.blogExcerpt = blogExcerpt;
}
public String getBlogContent() {
return blogContent;
}
public void setBlogContent(String blogContent) {
this.blogContent = blogContent;
}
public String getBlogThumbnail() {
return blogThumbnail;
}
public void setBlogThumbnail(String blogThumbnail) {
this.blogThumbnail = blogThumbnail;
}
public String getBlogMedimg() {
return blogMedimg;
}
public void setBlogMedimg(String blogMedimg) {
this.blogMedimg = blogMedimg;
}
public String getCategoryTitle() {
return categoryTitle;
}
public void setCategoryTitle(String categoryTitle) {
this.categoryTitle = categoryTitle;
}
}
Check if the server response is different then null before you do a enhanced for like this:
if(singleBlogPosts!= null) {
for (SingleBlogPosts posts : singleBlogPosts){
Log.d("AnotherSingleView","Please check RESPONSE: "+response.body().toString());
blogTitle.setText(posts.getBlogTitle());
blogSub.setText(posts.getBlogSubtitle());
blogContent.setText(posts.getBlogContent());
// Glide.with(AnotherSingleView.this).load(singlepost.getBlogMedimg()).into(blogPic);
}
}
you question was list iterator,but we can`t see you list use on anywhere,i guess you may be use recyclerView on you data has not get,because get data was asynchronous.try to use data if you can sure it is existing.
I have this JSON data and I'm trying to display "measurements" part, but it doesn't work.
(I'm getting this: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 2 path $).
I'm beginner at Android developing, this is my first app and I just don't know how to fix this.
Here JSON:
[{
"id":1,
"type":"TEMPERATURE",
"measurements":[
{
"value":"22.58",
"time":"2017-01-11T12:20:44.701"
}]
},{
"id":2,
"type":"HUMIDITY",
"measurements":[
{
"value":"52.366",
"time":"2017-01-11T12:20:44.731"
}]
},{
"id":3,
"type":"LUMINOSITY",
"measurements":[
{
"value":"1.0",
"time":"2017-01-11T12:20:44.742"
}]
}]
Adapter:
public class SenzoriAdapter extends RecyclerView.Adapter < SenzoriAdapter.ViewHolder > {
private ArrayList < Measurement > mSenzori;
public SenzoriAdapter(ArrayList < Measurement > senzori) {
this.mSenzori = senzori;
}
#Override
public SenzoriAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.main_item, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(SenzoriAdapter.ViewHolder viewHolder, int i) {
String datum = mSenzori.get(i).getTime().replace("T", " ");
viewHolder.senzoriLastAlive.setText(datum);
String stringdouble = Double.toString(mSenzori.get(i).getValue());
viewHolder.senzoriMeasurement.setText(stringdouble);
}
#Override
public int getItemCount() {
return mSenzori.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private TextView senzoriLastAlive, senzoriMeasurement;
public ViewHolder(View itemView) {
super(itemView);
senzoriLastAlive = (TextView) itemView.findViewById(R.id.senzoriLastAlive);
senzoriMeasurement = (TextView) itemView.findViewById(R.id.senzoriMeasurement);
}
}
}
Model Senzori:
public class Senzori {
#Expose
private Integer id;
#Expose
private String type;
#Expose
private Measurement[] measurements;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public Measurement[] getMeasurement() {
return measurements;
}
}
Model Measurement:
public class Measurement {
#Expose
private Double value;
#Expose
private String time;
public Double getValue() {
return value;
}
public void setValue(Double value) {
this.value = value;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
}
and usage in Activity:
public void configViews() {
mRecyclerView = (RecyclerView) findViewById(recyclerView);
mRecyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
mRecyclerView.setLayoutManager(layoutManager);
loadJSON();
}
public void loadJSON() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(MainActivity.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
SenzoriInterface request = retrofit.create(SenzoriInterface.class);
Call < Senzori > call = request.getAllSenzori(MainActivity.BASE_URL + "/sensors/");
call.enqueue(new Callback < Senzori > () {
#Override
public void onResponse(Call < Senzori > call, Response < Senzori > response) {
Senzori jsonResponse = response.body();
senzori = new ArrayList < > (Arrays.asList(jsonResponse.getMeasurement()));
senzoriAdapter = new SenzoriAdapter(senzori);
mRecyclerView.setAdapter(senzoriAdapter);
}
#Override
public void onFailure(Call < Senzori > call, Throwable t) {
Log.d("Error", t.getMessage());
}
});
}
You are expecting a single object, but response is giving you an array of objects.
Change
Call<Senzori> call = request.getAllSenzori(MainActivity.BASE_URL+"/sensors/");
To
Call<List<Senzori>> call = request.getAllSenzori(MainActivity.BASE_URL+"/sensors/");
And update your code accordingly.
call.enqueue(new Callback<List<Senzori>>() {
#Override
public void onResponse(Call<List<Senzori>> call, Response<List<Senzori>> response) {
senzori = response.body();
senzoriAdapter = new SenzoriAdapter(senzori.getMeasurement());
mRecyclerView.setAdapter(senzoriAdapter);
}
#Override
public void onFailure(Call<List<Senzori>> call, Throwable t) {
Log.d("Error",t.getMessage());
}
});