I am new to android development and I started working on an expandable RecyclerView. Now My problem is that my child (sub-modules) list is populated dynamically from the selected parent (Module) on the expandable RecyclerView. I tried using a for loop but only the last child list is populated when I open. I was just wondering if there is a way I could implement an item click listener to just return the single selected module.
Here is my adapter:
public class ReportAdapter extends ExpandableRecyclerViewAdapter<ModuleViewHolder, DoiViewHolder> {
Context context;
public ReportAdapter(List<? extends ExpandableGroup> groups, Context context) {
super(groups);
this.context = context;
}
#Override
public ModuleViewHolder onCreateGroupViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_module,parent,false);
return new ModuleViewHolder(view);
}
#Override
public DoiViewHolder onCreateChildViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_doi,parent,false);
return new DoiViewHolder(view);
}
#Override
public void onBindChildViewHolder(DoiViewHolder holder, int flatPosition, ExpandableGroup group, int childIndex) {
ModuleDoi moduleDoi =(ModuleDoi) group.getItems().get(childIndex);
holder.setDoiName(moduleDoi.getName());
}
#Override
public void onBindGroupViewHolder(ModuleViewHolder holder, int flatPosition, ExpandableGroup group) {
holder.setModuleName(group.getTitle());
}
}
Here is my Parent Holder:
public class ModuleViewHolder extends GroupViewHolder implements View.OnClickListener{
TextView moduleName ;
public ModuleViewHolder(View itemView) {
super(itemView);
moduleName = (TextView) itemView.findViewById(R.id.module_name);
}
public void setModuleName(String name){
moduleName.setText(name);
}
}
Here is my Childs holder (Sub Modules)
public class DoiViewHolder extends ChildViewHolder {
TextView doiName;
public DoiViewHolder(View itemView) {
super(itemView);
doiName = (TextView) itemView.findViewById(R.id.module_doi_name);
}
public void setDoiName(String name){
doiName.setText(name);
}
}
Here is where I set the adapter. I am using the
moduleDoiList = fetchModuleMenus(APPID, MODULENAME);
fetch the submodules list from a json file. the app id in this case is a constant and the MODULENAME is obtained from the Modules Array list.
JSONArray jsonArray = jsonObject.getJSONArray("RESPONSE");
moduleDoiList = new ArrayList<>();
appModulesList = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject eachModuleObject = jsonArray.getJSONObject(i);
MODULES modules = new MODULES(eachModuleObject.getString("MODULENAME"),
eachModuleObject.getString("MODULEID"));
ModulesList.add(modules);
for(int j = 0; j<ModulesList.size(); j++) {
String moduleTitle = ModulesList.get(i).getModuleName();
String MODULENAME = ModulesList.get(i).getModuleName();
moduleDoiList = fetchModuleMenus(APPID, MODULENAME);
appModulesList.add(new AppModules(moduleTitle, moduleDoiList));
}
}
reportAdapter = new ReportAdapter(appModulesList, POIDocsReportsActivity.this);
reportAdapter.notifyDataSetChanged();
rv.setAdapter(reportAdapter);
This is my fetchModulesMenu method:
public List<ModuleDoi> fetchModuleMenus(final String appId, final String moduleId) {
moduleDoiList = new ArrayList<>();
Thread thread = new Thread() {
Handler handler = new Handler();
ProgressDialog progressDialog;
boolean error;
#Override
public void run() {
handler.post(new Runnable() {
#Override
public void run() {
progressDialog = new ProgressDialog(POIDocsReportsActivity.this, R.style.Theme_AppCompat_DayNight_Dialog_Alert);
progressDialog.setMessage("Please wait...");
progressDialog.setCancelable(false);
progressDialog.show();
}
});
String url = AppConfig.SERVER_URL + "load_module_menus.php";
HashMap hashMap = new HashMap();
hashMap.put("APPID", appId);
hashMap.put("MODULEID", moduleId);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST,url, new JSONObject(hashMap), new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
progressDialog.dismiss();
JSONObject jsonObject = new JSONObject(response.toString());
error = jsonObject.getBoolean("ERROR");
if (error){
Toast.makeText(POIDocsReportsActivity.this, "MENUS NOT FOUND ", Toast.LENGTH_LONG).show();
}
else{
JSONArray jsonArray = jsonObject.getJSONArray("RESPONSE");
for (int i = 0; i < jsonArray.length(); i++){
JSONObject eachMenu = jsonArray.getJSONObject(i);
ModuleDoi moduleDoi = new ModuleDoi(eachMenu.getString("POINAME"), eachMenu.getString("POICODE"));
moduleDoiList.add(moduleDoi);
}
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(POIDocsReportsActivity.this, "CONNECTION ERROR ", Toast.LENGTH_LONG).show();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressDialog.dismiss();
Toast.makeText(POIDocsReportsActivity.this, "NO RESPONSE", Toast.LENGTH_LONG).show();
}
});
AppController.getInstance().addToRequestQueue(jsonObjectRequest);
}
};
thread.run();
return moduleDoiList;
}
I am using the Thoughtbot Custom Expandable Recycler View
Related
The app doesn't show anything in the recycler view the first time I open it, but it shows the items after I press the home button and then press the overview button and open the app from there
here is the code in mainActivity
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mlayoutManager;
private ProgressDialog dialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ArrayList<String> countryNmaeList =new ArrayList<>();
final ArrayList<countryItem> countryList = new ArrayList<>();
final ProgressDialog dialog = new ProgressDialog(this);
dialog.setMessage("Loading data");
mRecyclerView = findViewById(R.id.recyclerView);
mAdapter=new countryAdapter(countryList);
mlayoutManager=new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mlayoutManager);
dialog.show();
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://covid-193.p.rapidapi.com/statistics")
.get()
.addHeader("x-rapidapi-host", "covid-193.p.rapidapi.com")
.addHeader("x-rapidapi-key", "xxxxxxxxxxxxx")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
dialog.dismiss();
String response1=response.body().string();
try {
//geting Jason object
JSONObject jsonObject=new JSONObject(response1);
JSONArray jsonArray = jsonObject.getJSONArray("response");
for (int i=0;i<jsonArray.length();i++){
JSONObject country = jsonArray.getJSONObject(i);
JSONObject cases = country.getJSONObject("cases");
int activecaseint = cases.getInt("active");
int recoveredint =cases.getInt("recovered");
JSONObject death= country.getJSONObject("deaths");
int dtotal = death.getInt("total");
//adding items into country items
countryList.add(new countryItem(country.getString("country"),String.valueOf(activecaseint),String.valueOf(recoveredint),String.valueOf(dtotal)));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
//nottifying the dataset changed
mAdapter.notifyDataSetChanged();
mRecyclerView.setAdapter(mAdapter);
}
}
here is my adapter activity
countryAdapter.java
public class countryAdapter extends RecyclerView.Adapter<countryAdapter.countryViewHolder> {
private ArrayList<countryItem> mCountryList;
public static class countryViewHolder extends RecyclerView.ViewHolder{
public TextView mCountryName;
public TextView mActivePatients;
public TextView mRecovered;
public TextView mDeath;
public countryViewHolder(#NonNull View itemView) {
super(itemView);
mCountryName=itemView.findViewById(R.id.CountyNameTv);
mActivePatients=itemView.findViewById(R.id.activePatientsTv);
mRecovered=itemView.findViewById(R.id.recoveredTv);
mDeath=itemView.findViewById(R.id.deathTv);
}
}
public countryAdapter(ArrayList<countryItem> countryList){
mCountryList = countryList;
}
#NonNull
#Override
public countryViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v= LayoutInflater.from(parent.getContext()).inflate(R.layout.itemview,parent,false);
countryViewHolder cvh =new countryViewHolder(v);
return cvh;
}
#Override
public void onBindViewHolder(#NonNull countryViewHolder holder, int position) {
countryItem currentItem=mCountryList.get(position);
holder.mCountryName.setText(currentItem.getCountryname());
holder.mActivePatients.setText(currentItem.getActivePatients());
holder.mRecovered.setText(currentItem.getRecovered());
holder.mDeath.setText(currentItem.getDeath());
}
#Override
public int getItemCount() {
return mCountryList.size();
}
public void swapData(ArrayList<countryItem> list) {
if (list != null) {
this.mCountryList.clear();
this.mCountryList.addAll(list);
notifyDataSetChanged();
}
}
}
i have tried putting notifyDataSetChanged inside the try but that didn't work. i hope you can find a way to fix this.
When you have new datalist update after adding it in list as:
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
dialog.dismiss();
String response1=response.body().string();
try {
//geting Jason object
JSONObject jsonObject=new JSONObject(response1);
JSONArray jsonArray = jsonObject.getJSONArray("response");
for (int i=0;i<jsonArray.length();i++){
JSONObject country = jsonArray.getJSONObject(i);
JSONObject cases = country.getJSONObject("cases");
int activecaseint = cases.getInt("active");
int recoveredint =cases.getInt("recovered");
JSONObject death= country.getJSONObject("deaths");
int dtotal = death.getInt("total");
//adding items into country items
countryList.add(new countryItem(country.getString("country"),String.valueOf(activecaseint),String.valueOf(recoveredint),String.valueOf(dtotal)));
}
//adapter.swapData(countryList);
updateData(countryList);
} catch (JSONException e) {
e.printStackTrace();
}
}
you can comment out following line:
mAdapter.notifyDataSetChanged();
Add this function in your adapter class and call it when you need to update list:
public void swapData(ArrayList<countryItem> list) {
if (list != null) {
this.arrayList.clear();
this.arrayList.addAll(list);
notifyDataSetChanged();
}
}
In your global object declaration change type of adapter to:
private countryAdapter mAdapter;
add this method in mainActivity and call when you want to update data:
public void updateData(ArrayList<countryItem> countryList) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
mAdapter.swapData(countryList);
}
});
}
Instead of calling mAdapter.notifyDataSetChanged() at the end of onCreate() you should call it in onRespone() when the new data got set.
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
dialog.dismiss();
String response1=response.body().string();
try {
//geting Jason object
JSONObject jsonObject=new JSONObject(response1);
JSONArray jsonArray = jsonObject.getJSONArray("response");
for (int i=0;i<jsonArray.length();i++){
JSONObject country = jsonArray.getJSONObject(i);
JSONObject cases = country.getJSONObject("cases");
int activecaseint = cases.getInt("active");
int recoveredint =cases.getInt("recovered");
JSONObject death= country.getJSONObject("deaths");
int dtotal = death.getInt("total");
//adding items into country items
countryList.add(new countryItem(country.getString("country"),String.valueOf(activecaseint),String.valueOf(recoveredint),String.valueOf(dtotal)));
}
mAdapter.notifyDataSetChanged(); // ← notify adapter here!
} catch (JSONException e) {
e.printStackTrace();
}
}
I think ive looked at almost all threads wont seem to work.
Ive got a chat and im trying to update the list view every second im doing it on another thread however, im using runOnUiThread though it still wont update im logging the return and it seems there is a return every second with the correct data.
The code
protected void onCreate(Bundle savedInstanceState) {
........
lv = (ListView) findViewById(R.id.message_array);
returnFunc = "messages";
messages();
send = (ImageButton) findViewById(R.id.sendMessage);
send.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
returnFunc = "btnSend";
message = (EditText) findViewById(R.id.messageEditText);
message_input = message.getText().toString();
sendMessage();
}
});
new Thread(new Runnable() {
#Override
public void run() {
boolean test = true;
while (test) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}
messages();
}
}
}).start();
}
public static Handler handler = new Handler();
public void messageLoop(){
handler.postDelayed(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
messages();
handler.postDelayed(this,1000);
}
});
}
},1000);
}
the messages function which gets the data fine
public void messages() {
String urlParameters = String.format("%s", "chatid="+tempVars.chatID+"&token="+tempVars.token);
new AsyncHttpPost(this).execute("http://mylink.com/appAccess.php?action=messages&", urlParameters);
}
public void getMessages(String content){
myList = new ArrayList<Messages>();
int index = lv.getFirstVisiblePosition();
View v = lv.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - lv.getPaddingTop());
try{
JSONArray jsonarray = new JSONArray(content);
for (int i = 0; i < jsonarray.length(); i++) {
JSONObject jsonobject = jsonarray.getJSONObject(i);
boolean mine;
if(jsonobject.getString("isMine").equals("true")){
mine = true;
}else{
mine = false;
}
myList.add(new Messages(jsonobject.getString("message"),jsonobject.getString("timestamp"),jsonobject.getString("name"),mine,jsonobject.getString("id")));
}
}catch (Throwable tx){
}
lv.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> adapter, View v, int position, long arg3)
{
Messages CurrentMessage = myList.get(position);
tempVars.messageID = CurrentMessage.getID();
//startActivity(new Intent("PersonalChat"));
}
});
if(arrayAdapter == null){
arrayAdapter = new CustomAdapter(this, myList);
}
lv = (ListView) findViewById(R.id.message_array);
lv.setAdapter(arrayAdapter);
arrayAdapter.notifyDataSetChanged();
if(firstView == 0){
firstView = 1;
lv.setSelection(arrayAdapter.getCount() - 1);
}else{
lv.setSelectionFromTop(index, top);
}
}
class CustomAdapter
public class CustomAdapter extends ArrayAdapter<Messages>{
Messages currentMessage;
public CustomAdapter(Context context, ArrayList<Messages> messages){
super(context,R.layout.received_message, messages);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View itemView = convertView;
currentMessage = myList.get(position);
setTitle(currentMessage.getName());
if(currentMessage.isMine()){
itemView = getLayoutInflater().inflate(R.layout.sent_message,parent, false);
TextView message = (TextView) itemView.findViewById(R.id.message);
message.setText(currentMessage.getMessage());
TextView timestamp = (TextView) itemView.findViewById(R.id.date);
timestamp.setText(currentMessage.getTimestamp());
}else{
itemView = getLayoutInflater().inflate(R.layout.received_message,parent, false);
TextView message = (TextView) itemView.findViewById(R.id.message_text);
message.setText(currentMessage.getMessage());
TextView timestamp = (TextView) itemView.findViewById(R.id.timestamp);
timestamp.setText(currentMessage.getTimestamp());
}
return itemView;
}
}
Thanks in advance
More info
When i call the message function originally in onCreate it works fine
new Thread(new Runnable() {
#Override
public void run() {
boolean test = true;
while (test) {
try {
Thread.sleep(1000);
} catch (Exception e) {
}mymessage();
}
}
}).start();
Replace your getMessages() method with below code:
public void getMessages(String content){
myList = new ArrayList<Messages>();
int index = lv.getFirstVisiblePosition();
View v = lv.getChildAt(0);
int top = (v == null) ? 0 : (v.getTop() - lv.getPaddingTop());
try{
JSONArray jsonarray = new JSONArray(content);
for (int i = 0; i < jsonarray.length(); i++) {
JSONObject jsonobject = jsonarray.getJSONObject(i);
boolean mine;
if(jsonobject.getString("isMine").equals("true")){
mine = true;
}else{
mine = false;
}
myList.add(new Messages(jsonobject.getString("message"),jsonobject.getString("timestamp"),jsonobject.getString("name"),mine,jsonobject.getString("id")));
}
arrayAdapter.notifyDataSetChanged();
}catch (Throwable tx){
}
lv.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> adapter, View v, int position, long arg3)
{
Messages CurrentMessage = myList.get(position);
tempVars.messageID = CurrentMessage.getID();
//startActivity(new Intent("PersonalChat"));
}
});
if(arrayAdapter == null){
arrayAdapter = new CustomAdapter(this, myList);
}
lv = (ListView) findViewById(R.id.message_array);
lv.setAdapter(arrayAdapter);
if(firstView == 0){
firstView = 1;
lv.setSelection(arrayAdapter.getCount() - 1);
}else{
lv.setSelectionFromTop(index, top);
}
}
I am using a git repo called LikeButton, but the state of my button keeps jumping around in my recyclerview? Here is the repo https://github.com/jd-alexander/LikeButton. Basically when I click on a recyclerview item, it sets a textview to the word true or false based on if the user liked the post or not, and this works. However, the state of my button is doing some weird stuff, it jumps around...
Here is my Adapter, is their anything wrong with it?
public class ViewpagerAdapter extends RecyclerView.Adapter<ViewpagerAdapter.ViewDashboard>{
private LayoutInflater mLayoutInflater;
private ArrayList<QuestionData> data = new ArrayList<>();
public ViewpagerAdapter(Context context) {
mLayoutInflater=LayoutInflater.from(context);
}
public void setBloglist(ArrayList<QuestionData> listBlogs) {
this.data = listBlogs;
notifyItemRangeChanged(0,listBlogs.size());
}
#Override
public ViewDashboard onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mLayoutInflater.inflate(R.layout.customizejson, parent, false);
ViewDashboard viewholder = new ViewDashboard(view);
return viewholder;
}
#Override
public void onBindViewHolder(ViewDashboard holder, int position) {
QuestionData questionHolder = data.get(position);
holder.questionText.setText(questionHolder.getMtext());
//This sets the text, to a true or a false String
holder.mStudentVoted.setText(questionHolder.getVoters());
holder.mLikeButton.setTag(holder);
}
#Override
public int getItemCount() {
return data.size();
}
class ViewDashboard extends RecyclerView.ViewHolder {
private TextView questionText;
private LikeButton mLikeButton;
private TextView mStudentVoted;
public ViewDashboard(View itemView) {
super(itemView);
questionText = (TextView)itemView.findViewById(R.id.questionText);
mStudentVoted = (TextView)itemView.findViewById(R.id.studentVoted);
mLikeButton = (LikeButton)itemView.findViewById(R.id.like_button_viewpager);
mLikeButton.setOnLikeListener(new OnLikeListener() {
#Override
public void liked(LikeButton likeButton) {
Voting voting = new Voting(getAdapterPosition(),ViewpagerAdapter.this, questionId);
voting.onUpVote();
}
#Override
public void unLiked(LikeButton likeButton) {
Voting voting = new Voting(getAdapterPosition(),ViewpagerAdapter.this, questionId);
voting.onDownVote();
}
});
}
}
}
Voting Class
public class Voting {
private int adapterPosition;
private RecyclerView.Adapter adapter;
private String stringId;
private TextView studentVoted;
//TODO Trim Constructor
public Voting(int adapterPosition,final RecyclerView.Adapter adapter, TextView questionId, TextView studentVoted) {
stringId = questionId.getText().toString();
this.adapter = adapter;
this.studentVoted=studentVoted;
}
public void onUpVote() {
final RequestQueue mRequestQueue = VolleySingleton.getInstance().getRequestQueue();
StringRequest postVoteUp = new StringRequest(Request.Method.PUT, PUT_VOTE_UP, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println("Succesful Upvote The Students Value is " + studentVoted);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("failed Upvote");
}
});
mRequestQueue.add(postVoteUp);
}
public void onDownVote() {
final RequestQueue mrequestQueue = VolleySingleton.getInstance().getRequestQueue();
//TODO Delete Token(inserted for student 3 for testing purposes)
StringRequest postVoteDown = new StringRequest(Request.Method.PUT, PUT_VOTE_DOWN, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//TODO OnResponse, must setLiked(False)
//Succesful downVote The Students Value is true
//studentVoted.setText("false");
System.out.println("Succesful downVote The Students Value is "+studentVoted);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("failed downVote");
}
});
mrequestQueue.add(postVoteDown);
}
public void realTimeUpVoting(TextView textView){
String voteString= textView.getText().toString();
int voteNumber=Integer.parseInt(voteString)+1;
textView.setText("" + voteNumber);
}
public void realTimeDownVoting(TextView textView){
String voteString= textView.getText().toString();
int voteNumber=Integer.parseInt(voteString)-1;
textView.setText("" + voteNumber);
}
}
Json Request and Parsing Methods
public void JsonRequestMethod() {
mVolleySingleton = VolleySingleton.getInstance();
mRequestQueue = mVolleySingleton.getRequestQueue();
JsonArrayRequest request = new JsonArrayRequest(Request.Method.GET, URL_HOME, (String) null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
try {
mListblogs.clear();
mListblogs = new YourTask().execute(response).get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
mRequestQueue.add(request);
}
private ArrayList<QuestionData> parseJSONResponse(JSONArray response) {
if (!response.equals("")) {
try {
StringBuilder data = new StringBuilder();
for (int x = 0; x < response.length(); x++) {
JSONObject currentQuestions = response.getJSONObject(x);
JSONArray arrSubcategory = currentQuestions.optJSONArray("questions");
for (int y = 0; y < arrSubcategory.length(); y++) {
JSONObject objectSubcategory = arrSubcategory.getJSONObject(y);
String text = objectSubcategory.optString("text");
String studentId = objectSubcategory.optString("studentId");
String votes=objectSubcategory.optString("votes");
/*JSONArray cycles through the array of voters, when a user votes
their ID is added to the array.When they downvote, it is removed
*/
JSONArray voters= objectSubcategory.optJSONArray("voters");
QuestionData questionData = new QuestionData();
questionData.setMstudentId(studentId);
questionData.setMtext(text);
questionData.setVotes(votes);
questionData.setVoters(checkIfVoted(voters));
mQuestionDataArrayList.add(questionData);
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return mQuestionDataArrayList;
}
private static String checkIfVoted(JSONArray jsonArray ) {
/*pass in a json Array, copy the array into ints, and if
the students Id is contained in the array return the string true
*/
int[] voteIds = new int[jsonArray.length()];
for(int i=0;i<voteIds.length;i++){
voteIds[i] = jsonArray.optInt(i);
}
for(int i=0;i<voteIds.length;i++){
if(voteIds[i]== Integer.parseInt(Login.getUserId())){
//TODO String was only used for Testing purposes, Convert to Boolean later
return "true";
}
}
return "false";
}
you are currently only updating the textview which is why your recycleview changes state when scrolling.
Should change your voting class and pass the question Data rather textview
public Voting(int adapterPosition,final RecyclerView.Adapter adapter, TextView questionId, TextView studentVoted) {
change to
public Voting(int adapterPosition,final RecyclerView.Adapter adapter, QuestionData questionData, TextView studentVoted) {
// make other changes for the data
and then in
public void realTimeUpVoting(QuestionData questionData){
data.votes++ //something like that. idont know your model
// now call back using interface the recyleview data changed method so it updates the count in recycleview automatically.
Edit
passing the question Data in click button
class ViewDashboard extends RecyclerView.ViewHolder {
public int position
public void onBindViewHolder(ViewDashboard holder, int position) {
holder.position = position
}
public void liked(LikeButton likeButton) {
QuestionData questionHolder = data.get(position);
I have three classes, my adapter class, Voting class, and an acitivty where my JSONrequest is as shown below.The problem is as you can see that I call my JSONrequest in my activity which will get a list of views, inside that view I have a mVote textview. In my adapter you can also see I have a likeButton when someone presses that I would like mVotes to change from 0 to 1. I get all my data from a server so I am assuming I would need to make a new request, do I need to make a new adapter to? and JSON parseing method? How do I do this?!??!
public class AdapterQuestion extends RecyclerView.Adapter<AdapterQuestion.ViewQuestion>{
private LayoutInflater mLayoutInflater;
private ArrayList<QuestionData> data =new ArrayList<>();
public AdapterQuestion(Context context){
//get from context
mLayoutInflater=LayoutInflater.from(context);
}
public void setBloglist(ArrayList<QuestionData> data){
this.data =data;
notifyItemRangeChanged(0, this.data.size());
}
#Override
public ViewQuestion onCreateViewHolder(ViewGroup parent, int viewType){
ViewQuestion holder=new ViewQuestion(view);
return holder;
}
#Override
public void onBindViewHolder(ViewQuestion holder, int position) {
holder.answerText.setText(currentObj.getMtext());
holder.answerId.setText(currentObj.getId());
holder.mVotes.setText(currentObj.getVotes());
holder.mLikeButton.setTag(currentObj);
}
#Override
public int getItemCount() {
return data.size();
}
public class ViewQuestion extends RecyclerView.ViewHolder{
private TextView answerText;
private TextView answerId;
private TextView mVotes;
private LikeButton mLikeButton;
public ViewQuestion (View itemView){
super(itemView);
answerText=(TextView)itemView.findViewById(R.id.answerText);
answerId=(TextView)itemView.findViewById(R.id.answerId);
mVotes=(TextView)itemView.findViewById(R.id.VoteTextView);
mLikeButton= (LikeButton)itemView.findViewById(R.id.heart_buttons);
mLikeButton.setOnLikeListener(new OnLikeListener() {
#Override
public void liked(LikeButton likeButton) {
Voting vote = new Voting();
vote.onUpVote(answerId());
System.out.print("Adapter Position"+getAdapterPosition());
}
#Override
public void unLiked(LikeButton likeButton) {
Voting onDown=new Voting();
onDown.onDownVote(answerId());
}
});
}
public String getVoteView(){
String voteView=mVotes.getText().toString();
return voteView;
}
public String answerId(){
String converted=answerId.getText().toString();
return converted;
}
public int convertToInt(){
String converted=answerId.getText().toString();
int ConvertedInt=Integer.parseInt(converted);
return ConvertedInt;
}
}
}
Voting
public class Voting {
private VolleySingleton mVolleySingleton;
private RequestQueue mRequestQueue;
private AdapterVoteUpdate mAdapterVotes;
private ArrayList<QuestionData> updateVotes = new ArrayList<>();
public void onUpVote(final String answerId) {
final RequestQueue mrequestQueue = VolleySingleton.getInstance().getRequestQueue();
final String PUT_VOTE_UP = "url" + answerId + "url\n";
StringRequest PostVoteUp = new StringRequest(Request.Method.PUT, PUT_VOTE_UP, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
mrequestQueue.add(PostVoteUp);
}
public void onDownVote(final String answerId) {
System.out.println("Voted Down");
final RequestQueue mrequestQueue = VolleySingleton.getInstance().getRequestQueue();
final String PUT_VOTE_DOWN = "url" + answerId + "urul";
StringRequest PostVoteUp = new StringRequest(Request.Method.PUT, PUT_VOTE_DOWN, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
System.out.println("************Answer" + error + "error");
}
});
mrequestQueue.add(PostVoteUp);
}
JSON RequestClass
public void JsonRequestMethod(String Id) {
mVolleySingleton = VolleySingleton.getInstance();
mRequestQueue = mVolleySingleton.getRequestQueue();
final String URL_ANSWER = "url" + Id + "url";
JsonArrayRequest request = new JsonArrayRequest(Request.Method.GET, URL_ANSWER, (String) null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
mListblogs.clear();
mListblogs = parseJSONResponseQuestion(response);
mAdapterQuestion.setBloglist(mListblogs);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println(error);
}
});
mRequestQueue.add(request);
}
private ArrayList<QuestionData> parseJSONResponseQuestion(JSONArray response) {
if (!response.equals("")) {
ArrayList<QuestionData> questionDataArrayList = new ArrayList<>();
try {
StringBuilder data = new StringBuilder();
for (int i = 0; i < response.length(); i++) {
JSONObject currentQuestions = response.getJSONObject(i);
String text = currentQuestions.getString("text");
String questionId = currentQuestions.getString("questionId");
String votes = currentQuestions.getString("votes");
System.out.println(votes+" VOTES");
int voteInt=Integer.parseInt(votes);
System.out.println(voteInt);
String Answerid = currentQuestions.getString("id");
String selectedId = currentQuestions.getString("selected");
System.out.println(response.length() + "length");
data.append(text + Answerid + "\n");
System.out.println(data);
QuestionData questionData = new QuestionData();
questionData.setMtext(text);
questionData.setVotes(votes);
questionData.setId(Answerid);
questionData.setSelected(selectedId);
mListblogs.add(questionData);
}
System.out.println(data.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
return mListblogs;
}
"I get all my data from a server so I am assuming I would need to make a new request."
-> Actually you don't need to re-request the data from your server again. You just need to update
private ArrayList<QuestionData> data =new ArrayList<>();
on your AdapterQuestion then call AdapterQuestion.notifyDataSetChanged(); after you get a success response from onUpVote or onDownVote
"Do I need to make a new adapter to? and JSON parseing method? How do I do this?!??!"
-> No need
To change a particular ItemView in your recyclerview use this below code.
notifyItemChanged(index);
If you want to change the particular Textview in onItemclick you have to get the item position.
#Override
public void onBindViewHolder(ViewQuestion holder, int position) {
holder.answerText.setText(currentObj.getMtext());
holder.answerId.setText(currentObj.getId());
holder.mVotes.setText(currentObj.getVotes());
holder.mVotes.setTag(currentObj);
holder.mLikeButton.setTag(holder);
}
In your like button click event change the code like the below
mLikeButton.setOnLikeListener(new OnLikeListener() {
#Override
public void liked(LikeButton likeButton) {
Voting vote = new Voting();
vote.onUpVote(answerId());
final ViewQuestion holder=(ViewQuestionholder)likeButton.getTag();
currentObj co=(currentObj)holder.mVotes.getTag();
holder.mVotes.setText("16");
System.out.print("Adapter Position"+getAdapterPosition());
}
#Override
public void unLiked(LikeButton likeButton) {
Voting onDown=new Voting();
onDown.onDownVote(answerId());
final ViewQuestion holder=(ViewQuestionholder)likeButton.getTag();
currentObj co=(currentObj)holder.mVotes.getTag();
holder.mVotes.setText("14");
}
});
I am using an AsyncTask to connect to the following URL:
https://api.themoviedb.org/3/movie/upcoming?api_key=6572f232190d6b55ec917726dab87783
One of the values I am having trouble with is the genre_id. As it is a JSONArray I add the values to an ArrayList. I then later want to convert these values to the String correspondence which are found here:
http://api.themoviedb.org/3/genre/movie/list?api_key=6572f232190d6b55ec917726dab87783
// Genre is json array
JSONArray genreArry = obj.getJSONArray("genre_ids");
ArrayList<Integer> genre = new ArrayList<Integer>();
for (int j = 0; j < genreArry.length(); j++) {
genre.add(genreArry.optInt(j));
}
I'm just wondering what is the best way to do this? I am a displaying a ListView of all the information and for each row all the information is correct. I just need to convert the Genre id into the corresponding String. I have tried the code below but the TextView is always overwritten by the last value. Does anyone know of a better way to do this?
private void getGenre(int genre) {
for (int i = 0; i < genreList.size(); i++) {
Log.d("THE", "THE GENRE ADAPTER RETRIEVED IS" + i + genreList.get(i).getId() + genreList.get(i).getName());
if (genreList.get(i).getId() == genre) {
String name = genreList.get(i).getName();
mGenre.setText(name);
}
}
Solved.
I managed to get this working by doing a check in the onPostExecute of my AsyncTask
try {
JSONObject json = new JSONObject(result);
JSONArray movies = json.getJSONArray("results");
for (int i = 0; i < movies.length(); i++) {
JSONObject obj = movies.getJSONObject(i);
//Create Movie Object
Movie movie = new Movie();
//get values from JSON
movie.setTitle(obj.getString("original_title"));
movie.setPopularity(obj.getString("popularity"));
movie.setYear(obj.getString("release_date"));
movie.setThumbnailUrl(obj.getString("poster_path"));
movie.setOverView(obj.getString("overview"));
// Genre is json array
JSONArray genreArry = obj.getJSONArray("genre_ids");
ArrayList<Integer> genre = new ArrayList<Integer>();
ArrayList<String> genreName = new ArrayList<String>();
for (int j = 0; j < genreArry.length(); j++) {
genre.add(genreArry.optInt(j));
for (int zz = 0; zz < myGenreList.size(); zz++) {
if (myGenreList.get(zz).getId() == genre.get(j)) {
String name = myGenreList.get(zz).getName();
genreName.add(name);
}
}
}
movie.setGenre(genre);
movie.setGenreName(genreName);
I prefer Volley instead of AsyncTask for simplicity, but you are more than welcome to use either. Note, AsyncTask will require quite a bit more work.
From what I have provided here, you should be able to get my screenshot after building the ListView item XML.
I loosely followed this guide to get started quickly.
Screenshot
Movie.java - Model Object
public class Movie {
private int id;
private String title;
private List<String> genres;
public Movie() {
this(-1, null);
}
public Movie(int id, String title) {
this.id = id;
this.title = title;
this.genres = new ArrayList<String>();
}
public void addGenre(String s) {
this.genres.add(s);
}
public String getTitle() {
return title;
}
public List<String> getGenres() {
return genres;
}
}
MovieAdapter.java - ListView adapter
public class MovieAdapter extends ArrayAdapter<Movie> {
private final int layoutId;
public MovieAdapter(Context context, List<Movie> objects) {
super(context, 0, objects);
layoutId = R.layout.item_movie;
}
private static class ViewHolder {
TextView title;
TextView genres;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Movie movie = getItem(position);
ViewHolder viewHolder; // view lookup cache stored in tag
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = LayoutInflater.from(getContext());
convertView = inflater.inflate(layoutId, parent, false);
viewHolder.title = (TextView) convertView.findViewById(R.id.movie_title);
viewHolder.genres = (TextView) convertView.findViewById(R.id.movie_genres);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// Populate the data into the template view using the data object
viewHolder.title.setText(movie.getTitle());
viewHolder.genres.setText(String.valueOf(movie.getGenres()));
// Return the completed view to render on screen
return convertView;
}
}
MainActivity.java
public class MainActivity extends Activity {
private static final String GENRES_URL = "http://api.themoviedb.org/3/genre/movie/list?api_key=6572f232190d6b55ec917726dab87783";
private static final String MOVIES_URL = "https://api.themoviedb.org/3/movie/upcoming?api_key=6572f232190d6b55ec917726dab87783";
private HashMap<Integer, String> genreMap = new HashMap<Integer, String>();
private List<Movie> movies = new ArrayList<Movie>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView lv = (ListView) findViewById(R.id.listView);
final MovieAdapter movieAdapter = new MovieAdapter(this, movies);
lv.setAdapter(movieAdapter);
// Build the genres map
JsonObjectRequest request1 = new JsonObjectRequest(GENRES_URL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray genres = response.getJSONArray("genres");
for (int i = 0; i < genres.length(); i++) {
JSONObject genre = genres.getJSONObject(i);
int id = genre.getInt("id");
String name = genre.getString("name");
genreMap.put(id, name);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Network error", error.getMessage());
}
}
);
VolleyApplication.getInstance().getRequestQueue().add(request1);
JsonObjectRequest request2 = new JsonObjectRequest(MOVIES_URL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
movieAdapter.clear();
try {
JSONArray results = response.getJSONArray("results");
for (int i = 0; i < results.length(); i++) {
JSONObject result = results.getJSONObject(i);
int movieId = result.getInt("id");
String title = result.getString("original_title");
Movie movie = new Movie(movieId, title);
JSONArray genreIds = result.getJSONArray("genre_ids");
for (int j = 0; j < genreIds.length(); j++) {
int id = genreIds.getInt(j);
String genre = genreMap.get(id);
movie.addGenre(genre);
}
movieAdapter.add(movie);
}
} catch (JSONException e) {
Log.e("JSONException", e.getMessage());
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Network error", error.getMessage());
}
}
);
VolleyApplication.getInstance().getRequestQueue().add(request2);
}
}