NullPointerException with bundle and AsyncHttpTask - java

In my Android app I have a messages activity that is composed by three tabs (fragments: inbox, sent and deleted). I need to load data (received in JSON format and converted to String) in both tabs, but when I load the fragments app throws NullPointerException in the line where data is put in the bundle. I think that it's because the app hasn't received the information at the moment of its invocation.
To connect with the service provider i am using AsyncHttpTask library. Here is my code:
MessagesActivity.java:
public class MessagesActivity extends AppCompatActivity {
Toolbar toolbar;
ViewPager pager;
MessagesTabAdapter adapter;
SlidingTabLayout tabs;
CharSequence tabsTitles[] = {"Inbox","Sent","Trash"};
int tabsNumber = 3;
JSONObject inbox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.messages_activity);
//Elements initialization
...
adapter = new MessagesTabAdapter(getSupportFragmentManager(), tabsTitles, tabsNumber);
// Assigning ViewPager View and setting the adapter
pager = (ViewPager) findViewById(R.id.messages_pager);
pager.setAdapter(adapter);
// Assiging the Sliding Tab Layout View
tabs = (SlidingTabLayout) findViewById(R.id.messages_tabs);
tabs.setDistributeEvenly(true);
// Setting Custom Color for the Scroll bar indicator of the Tab View
tabs.setCustomTabColorizer(new SlidingTabLayout.TabColorizer() {
#Override
public int getIndicatorColor(int position) {
return getResources().getColor(R.color.tabsScrollColor);
}
});
// Setting the ViewPager For the SlidingTabsLayout
tabs.setViewPager(pager);
}
public void updateInbox () {
String token = getSharedPreferences("Myapp", Context.MODE_PRIVATE).getString("token", null);
RequestParams params = new RequestParams();
params.add("token", token);
Client.get("get_inbox", params, new JsonHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
try {
inbox = response.getJSONObject("result");
} catch (JSONException e) {
//No messages
inbox = new JSONObject();
}
}
});
}
public class MessagesTabAdapter extends FragmentStatePagerAdapter {
...
//This method return the fragment for the every position in the View Pager
#Override
public Fragment getItem(int position) {
if(position == 0) // if the position is 0 we are returning the First tab
{
Bundle bundle = new Bundle();
bundle.putString("inbox", updateInbox().toString()); //HERE IS MY EXCEPTION!
MessagesInboxTab tab1 = new MessagesInboxTab();
tab1.setArguments(bundle);
return tab1;
}
else if(position == 1) // As we are having 2 tabs if the position is now 0 it must be 1 so we are returning second tab
{
//Here will go the same code as position==0
MessagesSentTab tab2 = new MessagesSentTab();
return tab2;
}
else
{
//Here will go the same code as position==0
MessagesTrashTab tab3 = new MessagesTrashTab();
return tab3;
}
}
...
}
How can I solve?

You are getting null inside your updateInbox() method because you return null at its end, I think you wanted to return something else but you forgot to write it :)

The following method, always returning a null value.
public JSONObject updateInbox () {
String token = getSharedPreferences("Myapp", Context.MODE_PRIVATE).getString("token", null);
RequestParams params = new RequestParams();
params.add("token", token);
Client.get("get_inbox", params, new JsonHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response) {
try {
inbox = response.getJSONObject("result");
} catch (JSONException e) {
//No messages
inbox = null;
}
}
});
return null;
}
You should return inbox inside the try block.

Related

RecyclerView not showing any items unless i press homebutton and reenter the activity

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();
}
}

onItemSelected Listner are not trigger with the long String array from database

UPDATE:
I found the problem, the problem may cause by get the adapter content from SQL requset. Now I post my getLockerList() code here now.
I tested the function with long string
"asdajdnajkdaadasdaajd najkdaadasdaajdnajkdaadasdaajdnajkdaadasdaajdnaj kdaadasdaajdnajkdaadasdasdas"
and it still could work perfectly, so now I guess the problem is come from when I got the data.
I set a spinner with arrayadapter. The content of adapter is come from MySQL request.
I got the data and create the adapter successfully, but when I try to show what item was selected by user, it show nothing after I click the item.
I've tried add some system print to find out the problem, finally I found that the problem is the listener not even call, no matter onItemSelected or onNothingSelected
I think I may find the problem now, my view list is stored different location which is very long String. I tried change the content of the adapter to "test" and it work perfectly. So now the problem is now can I display the long string?
Here is my code:
public class PlaceOrderActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener {
private Spinner from_spinner;
private ArrayList<String> locker_list = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_place_order);
getLockerList();
from_spinner = (Spinner) findViewById(R.id.from_spinner);
from_spinner.setVisibility(View.VISIBLE);
ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_spinner_item,locker_list);
from_spinner.setAdapter(adapter);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
from_spinner.setOnItemSelectedListener(this);
}
private void getLockerList() {
// Response received from the server
Response.Listener<String> responseListener = new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONArray jsonResponse = new JSONArray(response);
//JSONObject jsonObject = jsonResponse.getJSONObject(0);
if (jsonResponse!=null) {
// System.out.println(jsonResponse);
for (int i=0;i< jsonResponse.length();i++)
{
JSONObject jsonObject = jsonResponse.getJSONObject(i);
String location = jsonObject.getString("location1")+" "+jsonObject.getString("location2")+" "+jsonObject.getString("location3");
locker_list.add(location);
}
} else {
}
} catch (JSONException e) {
e.printStackTrace();
}
}
};
Response.ErrorListener errorListener = new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println(error);
}
};
getLoockerLocationRequest request = new getLoockerLocationRequest(responseListener,errorListener);
RequestQueue queue = Volley.newRequestQueue(PlaceOrderActivity.this);
queue.add(request);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
System.out.println("selected item");
Toast.makeText(parent.getContext(),from_spinner.getSelectedItem().toString(),
Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
System.out.println("nothing select");
String no_selected_value = "Select the location";
Toast.makeText(parent.getContext(),no_selected_value,
Toast.LENGTH_SHORT).show();
}
}
I solved the problem.
I don't know what is the concept of it. But if I add one extra item to the arraylist, no matter the item is "" (just blank/nothing inside) or "#######################################"
The program will became could run perfectly.
So I just add one locker_list.add(""); before the adapter create.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_place_order);
locker_list.add("");
getLockerList();
from_spinner = (Spinner) findViewById(R.id.from_spinner);
from_spinner.setVisibility(View.VISIBLE);
ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_spinner_item,locker_list);
from_spinner.setAdapter(adapter);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
from_spinner.setOnItemSelectedListener(this);
}

Clearing my adapter

I populated a GridView with a Custom Adapter of images. I added a button to sort the images. I'm trying to figure out how to do this properly. As of right now, I'm trying to delete all the images by using the clear() method and repopulating it with the sorted images. However, I can't seem to delete the images. It just adds to the sorted images to the original. Please help
public class MainActivity extends AppCompatActivity {
private ImageView mImageView;
private TextView mTextView;
String githubSearchResults;
String default_sort = "http://api.themoviedb.org/3/movie/top_rated?api_key=(MY OWN API KEY)";
ArrayList<String> listdata = new ArrayList<String>();
List<String> posterData = new ArrayList<String>();
JSONObject results;
private MovieAdapter movieAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = (ImageView) findViewById(R.id.movie_image);
getURL(default_sort);
}
JSONArray getResults(String JSONString) throws JSONException {
JSONObject movieResults = new JSONObject(JSONString);
JSONArray jArray = (JSONArray)movieResults.getJSONArray("results");
if (jArray != null) {
for (int i=0;i<jArray.length();i++){
listdata.add(jArray.getString(i));
}
}
return jArray;
}
void getPosterPath() throws JSONException {
for(int i = 0;i<listdata.size();i++) {
results = new JSONObject(listdata.get(i));
String poster_path = results.getString("poster_path");
posterData.add(poster_path);
Log.d("myTag", poster_path);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.sort_popular, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.popular:
movieAdapter.clear();
movieAdapter.notifyDataSetChanged();
String sort_popular = "http://api.themoviedb.org/3/movie/popular?api_key=(MY OWN API KEY)";
getURL(sort_popular);
return true;
default:
super.onOptionsItemSelected(item);
}
return true;
}
private void getURL(String string){
URL getURL = NetworkUtils.buildUrl(string);
new GithubQueryTask().execute(getURL);
}
public class GithubQueryTask extends AsyncTask<URL, Void, String> {
// COMPLETED (2) Override the doInBackground method to perform the query. Return the results. (Hint: You've already written the code to perform the query)
#Override
protected String doInBackground(URL... params) {
URL searchUrl = params[0];
String githubSearchResults = null;
try {
githubSearchResults = NetworkUtils.getResponseFromHttpUrl(searchUrl);
getResults(githubSearchResults);
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return githubSearchResults;
}
// COMPLETED (3) Override onPostExecute to display the results in the TextView
#Override
protected void onPostExecute(String githubSearchResults) {
try {
getPosterPath();
} catch (JSONException e) {
e.printStackTrace();
}
movieAdapter = new MovieAdapter(MainActivity.this, posterData);
GridView listView = (GridView) findViewById(R.id.listview_flavor);
listView.setAdapter(movieAdapter);
}
}
}
Here's my custom adapter:
public class MovieAdapter extends ArrayAdapter<String> {
private ImageView mImageView;
public MovieAdapter(Activity context, List<String> movieArray) {
super(context, 0, movieArray);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String androidFlavor = getItem(position);
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.activity_detail, parent, false);
}
mImageView= (ImageView) convertView.findViewById(R.id.movie_image);
Picasso.with(getContext()).load("http://image.tmdb.org/t/p/w185/"+androidFlavor).into(mImageView);
return convertView;
}
}
If I'm not mistaking, the problem is you never clear posterData list (what about listdata as well). You just keep adding to it. I would suggest to change the getPosterPath method like this:
void getPosterPath() throws JSONException {
posterData.Clear();
for(int i = 0;i<listdata.size();i++) {
results = new JSONObject(listdata.get(i));
String poster_path = results.getString("poster_path");
posterData.add(poster_path);
Log.d("myTag", poster_path);
}
movieAdapter.notifyDataSetChanged();
}
And in public boolean onOptionsItemSelected you don't need to call
movieAdapter.clear();
movieAdapter.notifyDataSetChanged();
since any change in the list the adapter is bound to should reflect in the adapter after getPosterPath() gets executed.
EDIT:
The reason you get this error is because
movieAdapter = new MovieAdapter(MainActivity.this, posterData);
happens after the call to getPosterPath().
Just alter the onPostExectute() a bit:
protected void onPostExecute(String githubSearchResults) {
movieAdapter = new MovieAdapter(MainActivity.this, posterData);
try {
getPosterPath();
} catch (JSONException e) {
e.printStackTrace();
}
GridView listView = (GridView) findViewById(R.id.listview_flavor);
listView.setAdapter(movieAdapter);
}

How to update data to recylerview on click

I am developing an app, wherein I get JSON data and I am displaying it in the recylcer view. Now on click to the recycler view, on the basis of the item clicked I need to fetch the JSON data from the server and display it in the same recycler view. Its kind of recursive function. I am unable to find anything.
In the MainActivity, I have created an inner class for doing network task
new LauncherLoadThread(rootView).execute(appUsername, appPassword, loadURL, path);
class LauncherLoadThread extends AsyncTask<String, Integer, String[]> {
private View rootView;
public LauncherLoadThread(View rootView) {
this.rootView = rootView;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar.setVisibility(View.VISIBLE);
}
#Override
protected void onPostExecute(String[] strings) {
super.onPostExecute(strings);
progressBar.setVisibility(View.GONE);
if (strings != null) {
if (strings[0].contentEquals("200")) {
try {
String data = strings[1];
Log.d("Data", data);
JSONArray allData = new JSONArray(data);
for (int i = 0; i < allData.length(); i++) {
JSONObject jsonObject = allData.getJSONObject(i);
String id = jsonObject.getString("id");
String name = jsonObject.getString("name");
String path = jsonObject.getString("path");
String leaf = jsonObject.getString("leaf");
Log.d("Loaded Data: ", "Id: " + id + ". name: " + name + ". Path: " + path);
LauncherModel launcherModel=new LauncherModel(id,name,leaf,path);
launcherModelList.add(launcherModel);
}
adapter=new LauncherAdapter(launcherModelList,getContext());
launcherRecyclerView.setAdapter(adapter);
} catch (JSONException e) {
e.printStackTrace();
}
} else {
Snackbar snackbar = Snackbar.make(rootView, strings[0] + " Something broke down.", Snackbar.LENGTH_LONG);
View snackBarView = snackbar.getView();
TextView tv = (TextView) snackBarView.findViewById(android.support.design.R.id.snackbar_text);
snackbar.show();
}
} else {
Snackbar snackbar = Snackbar.make(rootView, "Oops something went wrong.", Snackbar.LENGTH_LONG);
View snackBarView = snackbar.getView();
TextView tv = (TextView) snackBarView.findViewById(android.support.design.R.id.snackbar_text);
snackbar.show();
}
}
#Override
protected String[] doInBackground(String... strings) {
String username = strings[0];
String password = strings[1];
String url = strings[2];
String path=strings[3];
String processURL="";
if(path.equals("")) {
processURL=url+"?path=Library";
}else {
processURL=url+"?path=" + path;
}
Log.d("doInBackURL", url);
String credential = Credentials.basic(username, password);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.get()
.addHeader("authorization", credential)
.addHeader("content-type", "application/json")
.build();
try {
Response response = client.newCall(request).execute();
if (response.isSuccessful()) {
String body = response.body().string();
Log.d("Body--->",body);
String code = response.code() + "";
Log.d("Code--->",code);
String[] output = {code, body};
return output;
} else {
String body = "Error: 404";
String code = response.code() + "";
String[] output = {code, body};
return output;
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
Here is my adapter onClickMethod:
public void onBindViewHolder(LauncherViewHolder holder, int position) {
LauncherModel launcherModel = listItem.get(position);
.......
.......
.......
.......
.......
.......
holder.launcherItemRelativeLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
}
});
}
Here you have many options depending on architecture you using. Basically, you can create interface like MyCustomItemClickListener:
interface MyCustomItemClickListener {
void onClick();
}
Than you extend MyCustomItemClickListener by Activity related to RecyclerView and override its method:
#Override
public void onClick(){
// basically, here goes the logic you want on click
}
As I assume you already have ViewHolder in Adapter, the simple option would be to pass Activity as custom Listener in your `Adapter. Than, if we choose this option, it should work like this:
//adapter's inner
class SomeClassViewHolder(val view: View) extends RecyclerView.ViewHolder(view) {
//here can be view initializing, like
txtHeader = (TextView) view.findViewById(R.id.audio_subtitle);
void bind(int position){
// all view binding logic goes here, for example:
txtHeader.setText("someText");
// AND here is also your listener working:
view.setOnClickListener{
listener.onItemClick(item)
}
}
}
//and then in adapter
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
holder.bind(values.get(position));
}
The only trick here is to pass the view(Activity or Fragment) as listener to custom Adapter and it should work.
Edit: For sure, with this approach you can simply reload data from activity with your own logic, like make another async request.
You can simply call notifyDataSetChanged() function of Adapter class.

How can I make sharedpreferences in Custom Adapter get the latest values of my ArrayList?

I use Volley in the onCreate of my Activity which gets a string on my server, then I convert this string to an arraylist,checkedContactsAsArrayList, and I pass it over to my custom adapter using sharedpreferences, which does stuff with the arraylist in the listview.
But the custom adapter keeps getting the previous arraylist in sharedpreferences, not the one I've just got from the server. The Volley call is too late or something - I can see in logcat the latest values are put after they are got, if you know what I mean.
For example:
VolleyCall 1 putString: 1,2,3
VolleyCall 2 putString: 4,5,6
VolleyCall 3 putString: 7,8,9
Custom Adapter 1 getString: gets values of the last time app was used
Custom Adapter 2 getString: 1,2,3
Custom Adapter 3 getString: 4,5,6
Any idea how to fix this? I could try doing the Volley call in the getView of my custom adapter but I've read on Stackoverflow that's bad practice.
Here are the relvant parts of my code - I've slimmed it down a bit, as there's a lot of stuff in there irrelevant to this issue.
Here's the code of my activity, ViewContact:
public class ViewContact extends AppCompatActivity implements android.widget.CompoundButton.OnCheckedChangeListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(activity_view_contact);
//selectPhoneContacts is an empty array list that will hold our SelectPhoneContact info
selectPhoneContacts = new ArrayList<SelectPhoneContact>();
listView = (ListView) findViewById(R.id.listviewPhoneContacts);
StringRequest stringRequest = new StringRequest(Request.Method.POST, ViewContact_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
//toast the response of ViewContact.php, which has been converted to a
//JSON object by the Php file with JSON encode
Toast.makeText(ViewContact.this, "OnResponse is" + response, Toast.LENGTH_LONG).show();
System.out.println("ViewContact: And the response is " + response);
try {
//checkedContacts is a String
String checkedContacts = responseObject.getString("checkedcontacts");
//convert the checkedContacts string to an arraylist
checkedContactsAsArrayList = new ArrayList<String>(Arrays.asList(checkedcontacts.split(",")));
System.out.println("ViewContact: checkedContactsAsArrayList is " + checkedContactsAsArrayList);
//we want to bring the checkedContactsAsArrayList array list to our SelectPhoneContactAdapter.
// It looks like Shared Preferences
//only works easily with strings so best way to bring the array list in Shared Preferences is with
//Gson.
//Here, we PUT the arraylist into the sharedPreferences
SharedPreferences sharedPreferencescheckedContactsAsArrayList = PreferenceManager.getDefaultSharedPreferences(getApplication());
SharedPreferences.Editor editorcheckedContactsAsArrayList = sharedPreferencescheckedContactsAsArrayList.edit();
Gson gsoncheckedContactsAsArrayList = new Gson();
String jsoncheckedContactsAsArrayList = gsoncheckedContactsAsArrayList.toJson(checkedContactsAsArrayList);
editorcheckedContactsAsArrayList.putString("checkedContactsAsArrayList", jsoncheckedContactsAsArrayList);
editorcheckedContactsAsArrayList.commit();
System.out.println("ViewContact: jsoncheckedContactsAsArrayList is " + jsoncheckedContactsAsArrayList);
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(),
"Error: " + e.getMessage(),
Toast.LENGTH_LONG).show();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(ViewContact.this, error.toString(), Toast.LENGTH_LONG).show();
}
}) {
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
//we are posting review_id into our ViewContact.php file, which
//we get when a row is clicked in populistolistview
//to get matching details
params.put("review_id", review_id);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//checkBoxforContact.setChecked(true);
}
//******for the phone contacts in the listview
// Load data in background
class LoadContact extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... voids) {
//we want to delete the old selectContacts from the listview when the Activity loads
//because it may need to be updated and we want the user to see the updated listview,
//like if the user adds new names and numbers to their phone contacts.
selectPhoneContacts.clear();
SelectPhoneContact selectContact = new SelectPhoneContact();
selectContact.setName(phoneNameofContact);
}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
adapter = new SelectPhoneContactAdapter(selectPhoneContacts, ViewContact.this,0);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
#Override
protected void onResume() {
super.onResume();
// getPrefs();
ViewContact.LoadContact loadContact = new ViewContact.LoadContact();
loadContact.execute();
Toast.makeText(ViewContact.this, "resuming!", Toast.LENGTH_SHORT).show();
}
}
And my custom adapter, SelectPhoneContactAdapter :
public class SelectPhoneContactAdapter extends BaseAdapter {
//define a list made out of SelectPhoneContacts and call it theContactsList
public List<SelectPhoneContact> theContactsList;
//define an array list made out of SelectContacts and call it arraylist
private ArrayList<SelectPhoneContact> arraylist;
Context _c;
ArrayList<String> MatchingContactsAsArrayList;
ArrayList<String> checkedContactsAsArrayList;
ArrayList <String> allNamesofContacts;
String contactToCheck;
//we will run through different logic in this custom adapter based on the activity that is passed to it
private int whichactivity;
String phoneNumberofContact;
String[] phoneNumberofContactStringArray;
String ContactsString;
Intent intent;
public SelectPhoneContactAdapter(final List<SelectPhoneContact> selectPhoneContacts, Context context, int activity) {
theContactsList = selectPhoneContacts;
_c = context;
this.arraylist = new ArrayList<SelectPhoneContact>();
this.arraylist.addAll(theContactsList);
whichactivity = activity;
//we are fetching the array list checkedContactsAsArrayList, created in ViewContact.
//with this we will put a tick in the checkboxes of contacts the review is being shared with
SharedPreferences sharedPreferencescheckedContactsAsArrayList = PreferenceManager.getDefaultSharedPreferences(_c);
Gson gsoncheckedContactsAsArrayList = new Gson();
String jsoncheckedContactsAsArrayList = sharedPreferencescheckedContactsAsArrayList.getString("checkedContactsAsArrayList", "");
Type type2 = new TypeToken<ArrayList<String>>() {
}.getType();
checkedContactsAsArrayList = gsoncheckedContactsAsArrayList.fromJson(jsoncheckedContactsAsArrayList, type2);
System.out.println("SelectPhoneContactAdapter checkedContactsAsArrayList :" + checkedContactsAsArrayList);
}
}
#Override
public int getCount() {
return arraylist.size();
}
#Override
public Object getItem(int i) {
return arraylist.get(i);
}
#Override
public long getItemId(int i) {
return i;
}
static class ViewHolder {
//In each cell in the listview show the items you want to have
//Having a ViewHolder caches our ids, instead of having to call and load each one again and again
TextView title, phone;
CheckBox check;
Button invite;
}
#Override
public View getView(final int i, View convertView, ViewGroup viewGroup) {
//this is the SelectPhoneContact object; consists of textboxes, buttons, checkbox
final SelectPhoneContact data = (SelectPhoneContact) arraylist.get(i);
ViewHolder holder = null;
if (convertView == null) {
//if there is nothing there (if it's null) inflate the view with the layout
LayoutInflater li = (LayoutInflater) _c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = li.inflate(R.layout.phone_inflate_listview, null);
holder = new ViewHolder();
//So, for example, title is cast to the name id, in phone_inflate_listview,
//phone is cast to the id called no etc
holder.title = (TextView) convertView.findViewById(R.id.name);
holder.phone = (TextView) convertView.findViewById(R.id.no);
holder.invite = (Button) convertView.findViewById(R.id.btnInvite);
holder.check = (CheckBox) convertView.findViewById(R.id.checkBoxContact);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
//in the listview for contacts, set the name
holder.title.setText(data.getName());
//in the listview for contacts, set the number
holder.phone.setText(data.getPhone());
holder.check.setTag(data);
return convertView;
}
}
Call this: loadContact.execute();
After you call .commit();
ViewContact.LoadContact loadContact = new ViewContact.LoadContact();
loadContact.execute();

Categories