I'm using YouTube Data API v3 for searching YouTube videos on my app.
Last night was working perfectly but now it keeps crashing when I click search button. Can someone help me?
I've tried to regenerate API key but same error
when I change to: return mVideoList.size();
Error is: E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.youtubeexampleproject, PID: 7031
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference at
YoutubeAdapter.getItemCount(YoutubeAdapter.java:108) the pointer goes to : return mVideolist.size();
and for code below error is:
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"location" : "fields",
"locationType" : "parameter",
"message" : "Invalid field selection activity",
"reason" : "invalidParameter"
} ],
"message" : "Invalid field selection activity"
}
'
query = youtube.search().list("id,snippet");
query.setKey(KEY);
query.setType("video");
query.setFields("items(id/kind,id/videoId,snippet/title,snippet/description,snippet/thumbnails/high/url/activity)");
} catch (IOException e) {
Log.d("YC", "Could not initialize: " + e);
}
}
public List<VideoItem> search(String keywords) {
query.setQ(keywords);
query.setMaxResults(MAXRESULTS);
try {
SearchListResponse response = query.execute();
List<SearchResult> results = response.getItems();
List<VideoItem> items = new ArrayList<VideoItem>();
if (results != null) {
items = setItemsList(results.iterator());
}
return items;
public class YoutubeAdapter extends RecyclerView.Adapter {
private Context mContext;
private List<VideoItem> mVideoList;
public class MyViewHolder extends RecyclerView.ViewHolder{
public ImageView thumbnail;
public TextView video_title, video_id, video_description;
public RelativeLayout video_view;
public MyViewHolder(View view) {
super(view);
thumbnail = view.findViewById(R.id.video_thumbnail);
video_title = view.findViewById(R.id.video_title);
video_id = view.findViewById(R.id.video_id);
video_description = view.findViewById(R.id.video_description);
video_view = view.findViewById(R.id.video_view);
}
}
public YoutubeAdapter(Context mContext, List<VideoItem> mVideoList) {
this.mContext = mContext;
this.mVideoList = mVideoList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.video_item, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final VideoItem singleVideo = mVideoList.get(position);
holder.video_id.setText("Video ID : "+singleVideo.getId()+" ");
holder.video_title.setText(singleVideo.getTitle());
holder.video_description.setText(singleVideo.getDescription());
Picasso.get()
.load(singleVideo.getThumbnailURL()).resize(480,270)
.centerCrop()
.into(holder.thumbnail);
holder.video_view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent();
intent.setClass(mContext, PlayerActivity.class);
intent.putExtra("VIDEO_ID", singleVideo.getId());
intent.putExtra("VIDEO_TITLE",singleVideo.getTitle());
intent.putExtra("VIDEO_DESC",singleVideo.getDescription());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return mVideoList == null ? 0 : mVideoList.size();
}
}'
Remove snippet/thumbnails/high/url/activity from fields and try
query.setFields("items(id/kind,id/videoId,snippet/title,snippet/description)");
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"
},
{
}
]
My sender messages & receiver messages are sent only in the sending messages and there is no in the received view.
I added the following code
database.getReference().child("chats")
.child(senderRoom)
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
messageModels.clear();
for (DataSnapshot snapshot1 : snapshot.getChildren())
{
MessageModel model = snapshot1.getValue(MessageModel.class);
model.setMessageId(snapshot1.getKey());
messageModels.add(model);
}
chatAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
but every time I send a new message the app gives the error of "the app is not responding"
and after that, as I said all sent messages appeared in sender view, not receivers.
This is the error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: myapp.files.memochatting, PID: 23966
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at myapp.files.memochatting.Adapter.ChatAdapter.onBindViewHolder(ChatAdapter.java:81)
The line (81) he refers to is:
viewHolder.senderMsg.setText(messageModel.getMessage());
My database looks like this:
{
"Users" : {
"9tDjCkxCnISIzOS1TvHmGwgFSG93" : {
"email" : "maha#gmail.com",
"password" : "123456789",
"userName" : "maha"
},
"PJFr3Lw0EcWLN275GdOqSDHR76D2" : {
"email" : "asmaa.11#gmail.com",
"password" : "123456789",
"userName" : "Asmaa"
},
"T9oPNFhHVadWySFt0ILA6D6XRRm1" : {
"email" : "ahmed#gmail.com",
"password" : "123456789",
"userName" : "ahmed"
},
"WtO1EJijSfgeF9JsVsMG7ZOSbjP2" : {
"profilePic" : "https://lh3.googleusercontent.com/a-/AOh14GggNZN75jHuTl1ZB5ZuQm26aXbT4DvLFGX1_OE0Kw=s96-c",
"userId" : "WtO1EJijSfgeF9JsVsMG7ZOSbjP2",
"userName" : "Maha Abd El-Moneam"
},
"moTrPYohePOFiX7kSLzOVYdbq1F2" : {
"email" : "mohamed#gmail.com",
"password" : "123456789",
"userName" : "mohamed"
}
},
"chats" : {
"9tDjCkxCnISIzOS1TvHmGwgFSG93PJFr3Lw0EcWLN275GdOqSDHR76D2" : {
"-MsdYoWZISiMbPaCDgLC" : {
"message" : "hello maha, I'm asmaa",
"timestamp" : 1641374739108,
"uId" : "9tDjCkxCnISIzOS1TvHmGwgFSG93"
},
"-Msd_2cuQOPDrU8G7_vS" : {
"message" : "hi asmaa",
"timestamp" : 1641375063018,
"uId" : "9tDjCkxCnISIzOS1TvHmGwgFSG93"
}
},
"9tDjCkxCnISIzOS1TvHmGwgFSG93WtO1EJijSfgeF9JsVsMG7ZOSbjP2" : {
"-MsdIrPbq7PFLRFSD-Pa" : {
"message" : "hellow from me",
"timestamp" : 1641370555853,
"uId" : "WtO1EJijSfgeF9JsVsMG7ZOSbjP2"
},
"-MsdIvG06F3EgjtdTzEY" : {
"message" : "please receive",
"timestamp" : 1641370570841,
"uId" : "WtO1EJijSfgeF9JsVsMG7ZOSbjP2"
},
"-MsdWGk0UBnm0Nch14uG" : {
"message" : "hello",
"timestamp" : 1641374072522,
"uId" : "9tDjCkxCnISIzOS1TvHmGwgFSG93"
},
"-MsdWukKtbmNNE8-lrPu" : {
"message" : "hi maha.gmail",
"timestamp" : 1641374240472,
"uId" : "9tDjCkxCnISIzOS1TvHmGwgFSG93"
}
},
"T9oPNFhHVadWySFt0ILA6D6XRRm1null" : {
"-MsKNncf-SlE2I-hwsj6" : {
"message" : "hello ahmed",
"timestamp" : 1641036308698
}
},
"WtO1EJijSfgeF9JsVsMG7ZOSbjP29tDjCkxCnISIzOS1TvHmGwgFSG93" : {
"-MsdIrEwWMoEep3buSCK" : {
"message" : "hellow from me",
"timestamp" : 1641370555853,
"uId" : "WtO1EJijSfgeF9JsVsMG7ZOSbjP2"
},
"-MsdIuv8E0e74zv_WyY4" : {
"message" : "please receive",
"timestamp" : 1641370570841,
"uId" : "WtO1EJijSfgeF9JsVsMG7ZOSbjP2"
},
"-MsdXVMa8zEt_sB0unfP" : {
"message" : "from maha to mahagmail",
"timestamp" : 1641374394307,
"uId" : "WtO1EJijSfgeF9JsVsMG7ZOSbjP2"
}
},
"WtO1EJijSfgeF9JsVsMG7ZOSbjP2null" : {
"-MsKNk5TBVnuhZikCdSs" : {
"message" : "hi maha",
"timestamp" : 1641036294080
},
"-MsdBScowXAo-Tti8zcM" : {
"message" : "please",
"timestamp" : 1641368615680
}
},
"nullT9oPNFhHVadWySFt0ILA6D6XRRm1" : {
"-MsKNnZQJNBVNdusyFax" : {
"message" : "hello ahmed",
"timestamp" : 1641036308698
}
},
"nullWtO1EJijSfgeF9JsVsMG7ZOSbjP2" : {
"-MsKNk-6YSAToqGxhD9O" : {
"message" : "hi maha",
"timestamp" : 1641036294080
},
"-MsdBSYC9LlNfrcaETS2" : {
"message" : "please",
"timestamp" : 1641368615680
}
}
}
}
public class MessageModel {
String uId, message, messageId;
Long timestamp;
public MessageModel(String uId, String message, Long timestamp) {
this.uId = uId;
this.message = message;
this.timestamp = timestamp;
}
public MessageModel(String uId, String message) {
this.uId = uId;
this.message = message;
}
public MessageModel(){
}
public String getuId() {
return uId;
}
public void setuId(String uId) {
this.uId = uId;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getMessageId() {
return messageId;
}
public void setMessageId(String messageId) {
this.messageId = messageId;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
}
public class ChatAdapter extends RecyclerView.Adapter {
ArrayList<MessageModel> messageModels;
Context context;
String recId;
int SENDER_VIEW_TYPE = 1;
int RECEIVER_VIEW_TYPE = 2;
public ChatAdapter(ArrayList<MessageModel> messageModels, Context context) {
this.messageModels = messageModels;
this.context = context;
}
public ChatAdapter(ArrayList<MessageModel> messageModels, Context context, String recId) {
this.messageModels = messageModels;
this.context = context;
this.recId = recId;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == SENDER_VIEW_TYPE)
{
View view = LayoutInflater.from(context).inflate(R.layout.sample_sender,parent,false);
return new SenderViewHolder(view);
}
else
{
View view = LayoutInflater.from(context).inflate(R.layout.sample_receiver,parent,false);
return new ReceiverViewHolder(view);
}
}
#Override
public int getItemViewType(int position) {
if(messageModels.get(position).getuId() == (FirebaseAuth.getInstance().getUid()))
{
return SENDER_VIEW_TYPE;
}
else
{
return RECEIVER_VIEW_TYPE;
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
MessageModel messageModel = messageModels.get(position);
if (holder.getClass() == SenderViewHolder.class)
{
SenderViewHolder viewHolder = (SenderViewHolder) holder;
viewHolder.senderMsg.setText(messageModel.getMessage());
}
else
{
ReceiverViewHolder viewHolder = (ReceiverViewHolder) holder;
viewHolder.receiverMsg.setText(messageModel.getMessage());
}
}
#Override
public int getItemCount() {
return messageModels.size();
}
public class ReceiverViewHolder extends RecyclerView.ViewHolder{
TextView receiverMsg, receiverTime;
public ReceiverViewHolder(#NonNull View itemView) {
super(itemView);
receiverMsg = itemView.findViewById(R.id.receiverText);
receiverTime = itemView.findViewById(R.id.receiverTime);
}
}
public class SenderViewHolder extends RecyclerView.ViewHolder{
TextView senderMsg, senderTime;
public SenderViewHolder(#NonNull View itemView) {
super(itemView);
senderMsg = itemView.findViewById(R.id.receiverText);
senderTime = itemView.findViewById(R.id.senderTime);
}
}
}
public class ChatDetailActivity extends AppCompatActivity {
ActivityChatDetailBinding binding;
FirebaseDatabase database;
FirebaseAuth auth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityChatDetailBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
getSupportActionBar().hide();
database = FirebaseDatabase.getInstance();
auth = FirebaseAuth.getInstance();
final String senderId = auth.getUid();
String recieveId = getIntent().getStringExtra("userId");
String userName = getIntent().getStringExtra("userName");
String profilePic = getIntent().getStringExtra("profilePic");
binding.userName.setText(userName);
Picasso.get().load(profilePic).placeholder(R.drawable.ic_avatar).into(binding.profileImage);
binding.backArrow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(ChatDetailActivity.this, MainActivity.class);
startActivity(intent);
}
});
final ArrayList<MessageModel> messageModels = new ArrayList<>();
final ChatAdapter chatAdapter = new ChatAdapter(messageModels,this,recieveId);
binding.chatRecyclerView.setAdapter(chatAdapter);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
binding.chatRecyclerView.setLayoutManager(layoutManager);
final String senderRoom = senderId + recieveId;
final String receiverRoom = recieveId + senderId;
binding.send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String message = binding.enterMessage.getText().toString();
final MessageModel model = new MessageModel(senderId, message);
model.setTimestamp(new Date().getTime());
binding.enterMessage.setText("");
database.getReference().child("chats")
.child(senderRoom)
.push()
.setValue(model).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void unused) {
database.getReference().child("chats")
.child(receiverRoom)
.push()
.setValue(model).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void unused) {
}
});
}
});
}
});
}
}
Replace
public class ReceiverViewHolder extends RecyclerView.ViewHolder{
TextView receiverMsg, receiverTime;
public ReceiverViewHolder(#NonNull View itemView) {
super(itemView);
receiverMsg = itemView.findViewById(R.id.receiverText);
receiverTime = itemView.findViewById(R.id.receiverTime);
}
}
with
public class ReceiverViewHolder extends RecyclerView.ViewHolder{
TextView receiverMsg, receiverTime;
public ReceiverViewHolder(#NonNull View itemView) {
super(itemView);
receiverMsg = itemView.findViewById(R.id.receiverText);
receiverTime = itemView.findViewById(R.id.receiverTime);
}
public void setData(MessageModel messageModel){
viewHolder.receiverMsg.setText(messageModel.getMessage());
}
}
and replace
public class SenderViewHolder extends RecyclerView.ViewHolder{
TextView senderMsg, senderTime;
public SenderViewHolder(#NonNull View itemView) {
super(itemView);
senderMsg = itemView.findViewById(R.id.receiverText);
senderTime = itemView.findViewById(R.id.senderTime);
}
}
with
public class SenderViewHolder extends RecyclerView.ViewHolder{
TextView senderMsg, senderTime;
public SenderViewHolder(#NonNull View itemView) {
super(itemView);
senderMsg = itemView.findViewById(R.id.receiverText);
senderTime = itemView.findViewById(R.id.senderTime);
}
public void setData(MessageModel messageModel){
viewHolder.receiverMsg.setText(messageModel.getMessage());
}
}
and then finally replace your onBindViewHolder with
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
MessageModel messageModel = messageModels.get(position);
if (getItemViewType(position) == SENDER_VIEW_TYPE) ((SenderViewHolder) holder).setData(messageModel);
else ((ReceiverViewHolder) holder).setData(messageModel);
}
I am not sure if it will help, but it surely will optimise your code.
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
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.
public class FragmentPatientsByVital extends Fragment {
private RecyclerView mRecyclerView;
private ArrayList<Patient> mList;
private AdapterVitalPatient mAdapter;
private MultiStateToggleButton mMultiStateToggleButton;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_patient_by_vital, container, false);
initUi(v);
if (mList != null)
updateList(mList);
return v;
}
private void initUi(View v) {
mRecyclerView = (RecyclerView) v.findViewById(R.id.recycler_view);
mMultiStateToggleButton = (MultiStateToggleButton) v.findViewById(R.id.mstb_multi_id);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mMultiStateToggleButton.setOnValueChangedListener(new ToggleButton.OnValueChangedListener() {
#Override
public void onValueChanged(int position) {
mAdapter.filterBy(position);
}
});
}
public void updateList(ArrayList<Patient> mList) {
if (mList == null) return;
this.mList = mList;
if (mAdapter == null)
mAdapter = new AdapterVitalPatient(mList);
mRecyclerView.setAdapter(mAdapter);
}
public static FragmentPatientsByVital newIntance() {
FragmentPatientsByVital f = new FragmentPatientsByVital();
return f;
}
}
Adapter
public class AdapterVitalPatient extends RecyclerView.Adapter<AdapterVitalPatient.ViewHolder> {
private ArrayList<Patient> mList;
public AdapterVitalPatient(ArrayList<Patient> mList) {
this.mList = mList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ViewHolder(InjectUtils.getInflator().inflate(R.layout.adapter_vital_patient, parent, false));
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Patient p = mList.get(position);
holder.mNameTextView.setText(p.getName());
if (mList.get(position).getSummary() != null) {
holder.updateRecords(mList.get(position).getSummary());
} else {
try {
holder.callApi(p.getEmail(), position);
} catch (Exception e) {
e.printStackTrace();
}
}
}
#Override
public int getItemCount() {
return mList.size();
}
public void filterBy(int position) {
switch (position) {
case 0: //!--- Any
break;
case 1: //!--- Normal
break;
case 2: //!--- High
break;
case 3: //!--- Low
break;
}
}
public class ViewHolder extends RecyclerView.ViewHolder {
private final TextView mNameTextView;
private final ProgressBar mProgressBar;
private final GridLayout mTableLayout;
public ViewHolder(View itemView) {
super(itemView);
mNameTextView = (TextView) itemView.findViewById(R.id.textview_title);
mProgressBar = (ProgressBar) itemView.findViewById(R.id.progress_bar);
mTableLayout = (GridLayout) itemView.findViewById(R.id.table_layout);
}
public void callApi(String email, final int pos) {
try {
RahaDelegates api = InjectUtils.getNetworkObj().create(RahaDelegates.class);
Call<String> call = api.getLatestVitals(String.format(RahaDelegates.GET_LATEST_VITALS, email));
InjectUtils.getNetworkClient().callApi(call, new ApiInterface() {
#Override
public void onResponse(boolean result, String completeResponse) {
Type token = new TypeToken<ArrayList<Vital>>() {
}.getType();
mList.get(getAdapterPosition()).setSummary((ArrayList<Vital>) InjectUtils.getGsonObj().fromJson(completeResponse, token));
updateRecords(mList.get(pos).getSummary());
mProgressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(String message) {
mProgressBar.setVisibility(View.GONE);
}
});
} catch (Exception e){
e.printStackTrace();
}
}
public void updateRecords(ArrayList<Vital> details) {
mTableLayout.setVisibility(View.VISIBLE);
mProgressBar.setVisibility(View.GONE);
mTableLayout.removeAllViews();
for (int i = 0; i < details.size(); i++) {
Log.e("List Size", String.valueOf(details.size()));
Vital v = details.get(i);
if (!v.getVitalName().toLowerCase().contains("lungreco") && !v.getVitalName().toLowerCase().contains("kickco")) {
View view = InjectUtils.getInflator().inflate(R.layout.adapter_home_vital_patient, mTableLayout, false);
mTableLayout.addView(view);
TextView name = (TextView) view.findViewById(R.id.vital_name);
TextView value = (TextView) view.findViewById(R.id.vital_value);
name.setText(v.getVitalName());
if (v.getVitalName().toLowerCase().contains("bodyc")) {
value.setText(v.getFat() + "/" + v.getMuscale() + " " + v.getUnit());
} else if (v.getVitalName().toLowerCase().contains("temp")) {
if (v.getValue() != null) {
value.setText(Math.round(Float.valueOf(v.getValue())) + " " + v.getUnit());
}
} else if (v.getVitalName().toLowerCase().contains("heartra")) {
value.setText(v.getValue());
} else if (v.getVitalName().toLowerCase().contains("etalbe")) {
value.setText(v.getValue() + " " + v.getUnit());
} else if (v.getVitalName().toLowerCase().contains("bloodpres")) {
value.setText(v.getSystolic() + "/" + v.getDiastolic() + " " + v.getUnit());
} else if (v.getVitalName().toLowerCase().contains("loodoxy")) {
value.setText(v.getValue() + " " + v.getUnit());
} else if (v.getVitalName().toLowerCase().contains("oodglucos")) {
value.setText(v.getValue() + " " + v.getUnit());
}
}
}
}
}
}
02-10 09:06:39.430 1600-1600/? E/BoostFramework: Exception java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[])' on a null object reference
02-10 09:06:39.476 16831-17154/? E/AndroidCll-SettingsSync: Could not get or parse settings
02-10 09:06:39.547 16831-17062/? E/Appboy v2.5.0 .bo.app.cj: Received server error from request: invalid_api_key
02-10 09:06:39.547 16831-17062/? E/Appboy v2.5.0 .bo.app.ci: Error occurred while executing Braze request: invalid_api_key
02-10 09:06:39.603 16831-17154/? E/AndroidCll-SettingsSync: Could not get or parse settings
02-10 09:06:39.759 1600-1600/? E/BoostFramework: Exception java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.lang.reflect.Method.invoke(java.lang.Object, java.lang.Object[])' on a null object reference
02-10 09:06:41.294 16594-16594/sa.digitrends.rahah.doctor E/AndroidRuntime: FATAL EXCEPTION: main
Process: sa.digitrends.rahah.doctor, PID: 16594
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
at sa.digitrends.doctor.adapter.AdapterVitalPatient$ViewHolder.updateRecords(AdapterVitalPatient.java:125)
at sa.digitrends.doctor.adapter.AdapterVitalPatient$ViewHolder$1.onResponse(AdapterVitalPatient.java:106)
at sa.app.base.retrofit.client.NetworkClient$1.onResponse(NetworkClient.java:60)
at retrofit2.ExecutorCallAdapterFactory$ExecutorCallbackCall$1$1.run(ExecutorCallAdapterFactory.java:68)
at android.os.Handler.handleCallback(Handler.java:754)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:163)
at android.app.ActivityThread.main(ActivityThread.java:6238)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:933)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:823)
02-10 09:06:41.761 16831-16831/? E/Referral: (LauncherApplication.java:890) restarted
You can remove below code segment from onBindView and add it inside another method that needs to fire when user do that relevant action
if (mList.get(position).getSummary() != null) {
holder.updateRecords(mList.get(position).getSummary());
} else {
try {
holder.callApi(p.getEmail(), position);
} catch (Exception e) {
e.printStackTrace();
}
}
then you can do notifydatasetchanged after get success response inside that public void onResponse(boolean result, String completeResponse)
It seems you have server error
Appboy v2.5.0 .bo.app.cj: Received server error from request: invalid_api_key 02-10 09:06:39.547 16831-17062/? E/Appboy v2.5.0 .bo.app.ci: Error occurred while executing Braze request: invalid_api_key 02-10 09:06:39.603 16831-17154
Error is due to NullPointerException
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
Update updateRecords methods as below
public void updateRecords(#Nullable ArrayList<Vital> details) {
mProgressBar.setVisibility(View.GONE);
if(details == null) {
return;
}
. . .
. . .
. . .
}
In general there can be further improvement made.
Avoid making API calls directly from Fragments or any Classes having views
Parse response in background thread. Below code might block your main thread for long time, when response is huge.
InjectUtils.getGsonObj().fromJson(completeResponse, token)