I am trying to parse a Block of JSON into a RecyclerView. So far I was able to achieve this with a quite flat JSON Structure. But now I have an Array-Entry in my JSON File where I always want to get the first Entry.
The JSON looks like this:
[
{
"MatchID": 60989,
"Team1": {
"TeamName": "FC Bayern München",
"TeamIconUrl": "https://i.imgur.com/jJEsJrj.png"
},
"Team2": {
"TeamName": "VfL Wolfsburg",
"TeamIconUrl": "https://i.imgur.com/ucqKV4B.png"
},
"MatchResults": [
{
"PointsTeam1": 4,
"PointsTeam2": 0,
"ResultOrderID": 1
},
{
"PointsTeam1": 1,
"PointsTeam2": 0,
"ResultOrderID": 2
}
]
},
{
"MatchID": 60990,
"Team1": {
"TeamName": "VfL Bochum",
"TeamIconUrl": "https://i.imgur.com/5jy3Gfr.png"
},
"Team2": {
"TeamName": "1. FC Union Berlin",
"TeamIconUrl": "https://upload.wikimedia.org/wikipedia/commons/4/44/1._FC_Union_Berlin_Logo.svg"
},
"MatchResults": [
{
"PointsTeam1": 0,
"PointsTeam2": 1,
"ResultOrderID": 1
},
{
"PointsTeam1": 0,
"PointsTeam2": 1,
"ResultOrderID": 2
}
]
}
]
My Activity fetches this JSON from an API using Retrofit2
private void parseJson() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.openligadb.de/api/")
.addConverterFactory(GsonConverterFactory.create())
.build();
RequestInterface request = retrofit.create(RequestInterface.class);
Call<List<Match>> call=request.getMatchJson();
call.enqueue(new Callback<List<Match>>() {
#Override
public void onResponse(Call<List<Match>> call, Response<List<Match>> response) {
if (response.isSuccessful() && response.body() != null) {
matchList = new ArrayList<>(response.body());
matchAdapter = new MatchAdapter(matchList, ActivityMatch.this);
mRecyclerView.setAdapter(matchAdapter);
}
}
#Override
public void onFailure(Call<List<Match>> call, Throwable t) {
Log.println(Log.ERROR, "FAILED", String.valueOf(t));
Toast.makeText(ActivityMatch.this, "Oops! Somehting went wrong!", Toast.LENGTH_SHORT).show();
}
});
}
My MatchAdapter is then parsing this Data for the View. Here I want to display whatever is the first in MatchResults then using PointsTeam1 and PointsTeam2 to display something like "4 : 0"
Now in my ModelClass accessing direct Values like the TeamName and TeamIconUrl worked but I am struggeling to get to the first entry of the Array and am really stuck on even how to properly approach this issue.
The Adapter Class:
public class MatchAdapter extends RecyclerView.Adapter<MatchAdapter.MatchHolder>{
private ArrayList<Match> matchList;
private Context context;
public MatchAdapter(ArrayList<Match> matchList, Context context) {
this.context = context;
this.matchList = matchList;
}
#NonNull
#Override
public MatchAdapter.MatchHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.match_list_row_layout, viewGroup, false);
return new MatchHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MatchAdapter.MatchHolder holder, int position) {
holder.tvTeam1name.setText(matchList.get(position).Team1.TeamName);
holder.tvTeam2name.setText(matchList.get(position).Team2.TeamName);
Glide.with(context).load(matchList.get(position).Team1.TeamIconUrl).into(holder.ivTeam1Logo);
Glide.with(context).load(matchList.get(position).Team2.TeamIconUrl).into(holder.ivTeam2Logo);
//This is not working
holder.tvResult.setText(matchList.get(position).MatchResults.PointsTeam1 + " : " + matchList.get(position).MatchResults.PointsTeam2);
}
#Override
public int getItemCount() {
return matchList.size();
}
public class MatchHolder extends RecyclerView.ViewHolder {
private TextView tvTeam1name, tvTeam2name, tvResult;
private ImageView ivTeam1Logo, ivTeam2Logo;
public MatchHolder(#NonNull View itemView) {
super(itemView);
tvTeam1name = itemView.findViewById(R.id.tv_team1name);
tvTeam2name = itemView.findViewById(R.id.tv_team2name);
tvResult = itemView.findViewById(R.id.tv_result);
ivTeam1Logo = itemView.findViewById(R.id.iv_team1logo);
ivTeam2Logo = itemView.findViewById(R.id.iv_team2logo);
}
}
}
My ModelClass (Left out Getters/Setters for Readability)
package de.eahjena.app.wi.fussball;
public class Match {
Team Team1;
Team Team2;
MatchResults MatchResults;
public Match(Team Team1, Team Team2, MatchResults MatchResults) {
this.Team1 = Team1;
this.Team2 = Team2;
this.MatchResults = MatchResults;
}
}
class Team {
String TeamName;
String TeamIconUrl;
public Team (String TeamName, String TeamIconUrl) {
this.TeamName = TeamName;
this.TeamIconUrl = TeamIconUrl;
}
}
class MatchResults {
String PointsTeam1;
String PointsTeam2;
public MatchResults(String PointsTeam1, String PointsTeam2) {
this.PointsTeam1 = PointsTeam1;
this.PointsTeam2 = PointsTeam2;
}
}
As per the question you are suppose to use List<MatchResults> MatchResults since the API response contains a list of match results.
Further to use the first position from the matchResults array you cna use it like this in your adapter :
matchList.get(position).MatchResults.get(0).PointsTeam1
Related
I want to know how to get a URL in a json and open it in a setOnClickListener of a RecyclerView
My API Json
{
{
"link": "https://example.com"
},
{
...
}
}
My URLModel
public class URLModel {
String Link;
public MonlixModel(String link) {
Link = link;
}
public String getLink() {
return Link;
}
public void setLink(String link) {
Link = link;
}
}
I think the problem comes from my Adapter but I don't know where and how to fix it
public class URLAdapter extends RecyclerView.Adapter<URLAdapter.URLHolder> {
Context mContext;
List<URLModel> urlModels;
public URLAdapter(Context mContext, List<URLAdapter> urlModels) {
this.mContext = mContext;
this.urlModels= urlModels;
}
#NonNull
#Override
public URLHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.recycler_view, parent, false);
return new URLHolder(view);
}
#Override
public void onBindViewHolder(#NonNull URLHolder holder, int position) {
holder.recyclerUrl.setOnClickListener(view -> {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(urlModels.get(position).getLink()));
mContext.startActivity(intent);
});
}
#Override
public int getItemCount() {
return urlModels.size();
}
public static class URLHolder extends RecyclerView.ViewHolder {
private final RecyclerView recyclerUrl;
public URLHolder(#NonNull View itemView) {
super(itemView);
recyclerUrl = itemView.findViewById(R.id.recycler_url);
}
}
}
And finally my Main.java
private void getData() {
RequestQueue requestQueue = Volley.newRequestQueue(this);
#SuppressLint("NotifyDataSetChanged") JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, Apis.JSON_API, null, response -> {
for(int i = 0; i <=response.length(); i++){
try {
JSONObject jsonObject = response.getJSONObject(i);
URLModelList.add(new URLModel(
jsonObject.getString("link")
));
} catch (JSONException e) {
e.printStackTrace();
}
}
URLAdapter adapter = new URLAdapter(getApplicationContext(), URLModelList);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
Toast.makeText(Main.this, "Success", Toast.LENGTH_SHORT).show();
}, error -> Toast.makeText(Main.this, error.getMessage(), Toast.LENGTH_SHORT).show());
requestQueue.add(jsonArrayRequest);
}
I use Volley, I don't know if it's the most adapted but I succeeded with that, I also tried to change in my URLModel the String by a Uri. But I noticed that the JSONObject didn't have a getUri or something like that
In my Logcat it tells me it's a null object reference
Any help will be much appreciated!
Please check your JSON format first,
{
"key_name1": {
"link": "https://example.com"
},
"key_name2":{
...
}
}
make sure your inner object should have key_name as above example or make this JSONObject to JSONArray like this
[
{
"link": "https://example.com"
},
{
}
]
How do I remove all null and empty string values from an object in JSON java android from retrofit?
Filter out any items where "name" is blank or null.
this is my Main Activity
Api api = retrofit.create(Api.class);
Call<List<MainData>> call = api.getData();
call.enqueue(new Callback<List<MainData>>() {
#Override
public void onResponse (Call<List<MainData>> call, Response<List<MainData>> response) {
if (!response.isSuccessful()) {
Toast.makeText(MainActivity.this, response.code(), Toast.LENGTH_SHORT).show();
return;
}
List<MainData> postList = response.body();
// Filter out any items where "name" is blank or null.
List<MainData> tempList = new ArrayList<>();
for(MainData data :postList)
{
if(null!= data.getName() && !data.getName().isEmpty()) {
//sort by name
Collections.sort(tempList, (mainData, t1) -> mainData.getName().compareTo(t1.getName()));
//sort by ListId
Collections.sort(tempList, (mainData, t1) -> mainData.getListId().compareTo(t1.getListId()) );
tempList.add(data);
}
}
RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(tempList, MainActivity.this);
recyclerView.setAdapter(recyclerViewAdapter);
}
#Override
public void onFailure (Call<List<MainData>> call, Throwable t) {
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
This Is My Adpater
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
//initialize variables
List<MainData> dataArrayList;
Context context;
//create constructor
public RecyclerViewAdapter (Context context, List<MainData> dataArrayList) {
this.dataArrayList = dataArrayList;
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder (#NonNull ViewGroup parent, int viewType) {
//this method recycling the view holder
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder (#NonNull ViewHolder holder, int position) {
//initialize Main data
MainData data = dataArrayList.get(position);
//set name on text view
holder.listId.setText(String.format("list_id : %s", data.getListId()));
holder.name.setText(String.format("name : %s", data.getName()));
holder.id.setText(String.format("id : %s", data.getId()));
}
#Override
public int getItemCount () {
return dataArrayList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
//initialize variables
TextView listId, name, id;
public ViewHolder (#NonNull View itemView) {
super(itemView);
//assign variables
listId = itemView.findViewById(R.id.list_id);
name = itemView.findViewById(R.id.name);
id = itemView.findViewById(R.id.id);
}
}
}
this is the Data
public class MainData {
public String listId, name, id;
public String getListId () {
return listId;
}
public String getName () {
return name;
}
public String getId () {
return id;
}
}
And this is the Api
public interface Api {
#GET("hiring.json")
Call<List<MainData>> getData();
}
And this is my app I want to remove nulls and emp
enter image description here
There are two ways
(1) While inflating the data you can filter these unwanted values
(2) Create a temporary list and add only required values from the main list.
sample code:
List<MainData> tempList = new ArrayList<>();
for(MainData data :postList)
{
if(null!= data.getName() && !data.getName().isEmpty())
{ tempList.add(data);
}
}
And then pass this tempList to the adapter.
Final code would look like this.
Api api = retrofit.create(Api.class);
Call<List<MainData>> call = api.getData();
call.enqueue(new Callback<List<MainData>>() {
#Override
public void onResponse (Call<List<MainData>> call, Response<List<MainData>> response) {
if (!response.isSuccessful()) {
Toast.makeText(MainActivity.this, response.code(), Toast.LENGTH_SHORT).show();
return;
}
List<MainData> postList = response.body();
//sort by ListId
Collections.sort(postList, (mainData, t1) -> mainData.getListId().compareTo(t1.getListId()));
// Filter out any items where "name" is blank or null.
List<MainData> tempList = new ArrayList<>();
for(MainData data :postList)
{
if(null!= data.getName() && !data.getName().isEmpty())
{ tempList.add(data);
}
}
RecyclerViewAdapter recyclerViewAdapter = new RecyclerViewAdapter(MainActivity.this, tempList );
recyclerView.setAdapter(recyclerViewAdapter);
}
#Override
public void onFailure (Call<List<MainData>> call, Throwable t) {
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
Feel free to ask if something is unclear.
First let me say, I have searched before posting, just cant find the answer.
I want To Get an api which is Like this
[
1,
2,
3,
4,
5,
6,
7
]
and then add RecylerView .
Model
Seats.java
////////////////////////////////////////////////
////////////////////////////////
import com.google.gson.annotations.SerializedName;
public class Seats {
#SerializedName("seatNo")
private int seatNo;
public int getSeatNo() {
return seatNo;
}
public void setSeatNo(int seatNo) {
this.seatNo = seatNo;
}
#Override
public String toString() {
return
"seats{" +
"unique_id = '" + seatNo + '\'' +
"}";
}
}
SeatsAdapter
public class SeatsAdapter extends RecyclerView.Adapter<SeatsAdapter.SeatsViewHolder> {
private SeatsActivity seatsActivity;
private Context context;
private ArrayList<Seats> seatsList;
//Context ctx;
public SeatsAdapter(SeatsActivity seatsActivity, Context context, ArrayList<Seats> seatsList) {
this.seatsList = seatsList;
this.seatsActivity = seatsActivity;
this.context = context;
//this.ctx = ctx;
}
#Override
public SeatsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout
.item_seat, parent, false);
return new SeatsViewHolder(view);
}
#Override
public void onBindViewHolder(final SeatsViewHolder holder, int position) {
final Seats seats = seatsList.get(position);
holder.mTvSeatNo.setText(seats.getSeatNo());
}
#Override
public int getItemCount() {
return seatsList.size();
}
protected class SeatsViewHolder extends RecyclerView.ViewHolder {
private final ImageView mIvSeatSelected;
private ImageView mIvSeat, mTvSeatLadies, mIvSeatBooked;
private TextView mTvSeatNo;
public SeatsViewHolder(View itemView) {
super(itemView);
mIvSeat = itemView.findViewById(R.id.ivSeat);
mIvSeatSelected = itemView.findViewById(R.id.ivSeatSelected);
mTvSeatNo = itemView.findViewById(R.id.tvSeatNo);
mTvSeatLadies = itemView.findViewById(R.id.ivSeatLadies);
mIvSeatBooked = itemView.findViewById(R.id.ivSeatBooked);
}
}
}
And Here is activity.java
private void initParcelRcv() {
seatsList = new ArrayList<Seats>();
rcvSeat= (RecyclerView) findViewById(R.id.rcvSeat);
rcvSeat.setLayoutManager(new LinearLayoutManager(this));
SeatsAdapter = new SeatsAdapter(this,this,seatsList);
rcvSeat.setAdapter(SeatsAdapter);
}
private void getSeatsInfo() {
Utils.showCustomProgressDialog(this, getResources().getString(R.string
.msg_waiting_for_get_documents),
false, null);
Call<List<Seats>> call = ApiClient.getClient().create(ApiInterface.class)
.getSeats(busName,departure,arrival,departuretime);
call.enqueue(new Callback<List<Seats>>() {
#Override
public void onResponse(Call<List<Seats>> call, Response<List<Seats>> response) {
if (parseContent.isSuccessful(response)) {
List<Seats> seats = response.body();
seatsList.addAll(Arrays.asList(seats.toArray()));
SeatsAdapter.notifyDataSetChanged();
Utils.hideCustomProgressDialog();
}
else {
Utils.showErrorToast(response.body().hashCode(),
SeatsActivity.this);
Utils.hideCustomProgressDialog();
}
}
#Override
public void onFailure(Call<List<Seats>> call, Throwable t) {
AppLog.handleThrowable(SeatsActivity.class.getSimpleName(), t);
Utils.showToast(SeatsActivity.class.getSimpleName(), SeatsActivity.this
);
Utils.hideCustomProgressDialog();
}
});
}
Your code expects "{", but found a number instead. You should check your JSON first (please, write a resulting JSON in your question, I think it is [ 1, 2, 3, 4, 5, 6, 7 ]).
I see you use this POJO in Seats.java:
#SerializedName("seatNo")
private int seatNo;
This is a wrong model, because your JSON consists of a list of integers.
Maybe you should remove Seats.java and rewrite a callback:
call.enqueue(new Callback<List<Integer>>() {
UPDATE
Simply replace Seats with Integer (I didn't check).
Call<List<Integer>> call = ApiClient.getClient().create(ApiInterface.class)
.getSeats(busName,departure,arrival,departuretime);
call.enqueue(new Callback<List<Integer>>() {
#Override
public void onResponse(Call<List<Integer>> call, Response<List<Integer>> response) {
if (parseContent.isSuccessful(response)) {
List<Integer> seats = response.body();
seatsList.addAll(Arrays.asList(seats.toArray()));
SeatsAdapter.notifyDataSetChanged();
Utils.hideCustomProgressDialog();
}
else {
Utils.showErrorToast(response.body().hashCode(),
SeatsActivity.this);
Utils.hideCustomProgressDialog();
}
}
#Override
public void onFailure(Call<List<Integer>> call, Throwable t) {
AppLog.handleThrowable(SeatsActivity.class.getSimpleName(), t);
Utils.showToast(SeatsActivity.class.getSimpleName(), SeatsActivity.this
);
Utils.hideCustomProgressDialog();
}
});
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.
I have generated dynamic forms according to type i.e String, int and spinner according to the json data provided by backend.
I have created a recylerview adapter and in pojo class I have added extra variable as answer and provided setter method to it.
Now, forms have generated according to type but I need to save data to server. To save data, i need to get each edittext value with respective id and type and I need to loop it but I couldnot do it so. I cannot define the edittext value with its ID and type. I hope you guys will help me.
There are three paramters to post to server,in method callRetrofitSaveForm() i. vendorId, ii. userid
iii. formData, I have problem with param iii because it has its format to pass. I have used retrofit to parse and problem is with third parameter formData.
the value format of third paramter is
[{"id":"24","label":"Customer ID","value":"102"},{"id":"25","label":"Amount","value":"2000"}]
My Adapter
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
HelpForm.FormSetting formSetting=formArrayList.get(position);
final String description = formArrayList.get(position).getLabel();
Log.d("cjjdnjcnjd",description);
if (formSetting.getType().equals("STRING")){
Log.d("dndjkd",String.valueOf(holder.getAdapterPosition()));
holder.textViewString = new TextView(activity);
holder.linearLayout.addView(holder.textViewString);
holder.textViewString.setText(formSetting.getLabel());
holder.textViewString.setPadding(24, 4, 24, 2);
holder.textViewString.setTextColor(context.getResources().getColor(R.color.colorTexts));
holder.textViewString.setTextSize(15);
holder.editTextString = new EditText(activity);
holder.linearLayout.addView(holder.editTextString);
editTextListString.add(holder.editTextString);
}
if (formSetting.getType().equals("INT")){
holder.textViewInt = new TextView(activity);
holder.linearLayout.addView(holder.textViewInt);
holder.textViewInt.setText(formSetting.getLabel());
holder.textViewInt.setPadding(24, 4, 24, 2);
holder.textViewInt.setTextColor(context.getResources().getColor(R.color.colorTexts));
holder.textViewInt.setTextSize(15);
holder.editTextINT = new EditText(activity);
holder.linearLayout.addView(holder.editTextINT);
}
if (formSetting.getType().equals("DATE")){
holder.textViewDate = new TextView(activity);
holder.linearLayout.addView(holder.textViewDate);
holder.textViewDate.setText(formSetting.getLabel());
holder.textViewDate.setPadding(24, 4, 24, 2);
holder.textViewDate.setTextColor(context.getResources().getColor(R.color.colorTexts));
holder.textViewDate.setTextSize(15);
holder.editTextDate = new EditText(activity);
holder.linearLayout.addView(holder.editTextDate);
}
if(formSetting.getType().equals("DROPDOWN")){
holder.textViewSpinner = new TextView(context);
holder.linearLayout.addView(holder.textViewSpinner);
holder.textViewSpinner.setText(formSetting.getLabel());
holder.textViewSpinner.setPadding(16, 4, 8, 4);
holder.spinner = new Spinner(context);
holder.linearLayout.addView(holder.spinner);
ArrayList<String> err = new ArrayList<>();
err = formSetting.getOptions();
holder.spinner.setAdapter(new ArrayAdapter<String>(context, android.R.layout.simple_dropdown_item_1line, err));
}
VendorFormActivity.save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
callRetrofitSaveForm();
}
});
}
#Override
public int getItemCount() {
return formArrayList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView textViewString,textViewInt,textViewDate;
LinearLayout linearLayout;
EditText editTextString,editTextINT,editTextDate;
Spinner spinner;
TextView textViewSpinner;
public MyViewHolder(View itemView) {
super(itemView);
linearLayout=itemView.findViewById(R.id.dynamiccontainer);
}
}
JSON Response
{
"status": "200",
"message": "success",
"formSetting": [
{
"label": "Customer ID",
"id": 24,
"type": "INT"
},
{
"label": "Amount",
"id": 25,
"type": "INT"
}
]
}
HelpForm
public class HelpForm {
#SerializedName("status")
#Expose
public String status;
#SerializedName("message")
#Expose
public String message;
#SerializedName("formSetting")
#Expose
public ArrayList<FormSetting> formSetting = null;
public ArrayList<FormSetting> getFormSetting() {
return formSetting;
}
public String getStatus() {
return status;
}
public String getMessage() {
return message;
}
public class FormSetting {
#SerializedName("options")
#Expose
public ArrayList<String> options = null;
#SerializedName("label")
#Expose
public String label;
#SerializedName("id")
#Expose
public String id;
#SerializedName("type")
#Expose
public String type;
#SerializedName("answer")
#Expose
public String answer;
public ArrayList<String> getOptions() {
return options;
}
public String getLabel() {
return label;
}
public String getId() {
return id;
}
public String getType() {
return type;
}
public void setAnswer(String answer) {
this.answer = answer;
}
}
}
public void callRetrofitSaveForm() {
RestClient.RetroInterfaceAPI mInterface = RestClient.getClient();
Call<SaveForm> call = mInterface.getSaveForm( vendorID, userID,formData);
call.enqueue(new Callback<SaveForm>() {
#Override
public void onResponse(Call<SaveForm> call, Response<SaveForm> response) {
if (response.body() != null) {
}
}
#Override
public void onFailure(Call<SaveForm> call, Throwable t) {
}
});
}
}
You can grab the parent view and loop through it and get all editText.
private HashSet<EditText> getTextViews(ViewGroup root){
HashSet<EditText> views=new HashSet<>();
for(int i=0;i<root.getChildCount();i++){
View v=root.getChildAt(i);
if(v instanceof EditText){
views.add((EditText)v);
}else if(v instanceof ViewGroup){
views.addAll(getTextViews((ViewGroup)v));
}
}
return views;
}