Error fetching data from server into fragment using volley - java

I have a json data from a url in which I want to fetch text data from using volley library. I have also a fragment in which the data would be shown.
Volley gives me an error after fetching the data and I have no idea what am doing wrong.
The onErrorResponse function gets called again and again and the toast message is shown - Something went wrong.
Here's the Fragment.java
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View view = inflater.inflate(R.layout.fragment, container, false);
final TextView textView = view.findViewById(R.id.event_text);
}
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, Config.events_server, (String) null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
textView.setText(response.getString("trending"));
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(view.getContext(), "Something went wrong", Toast.LENGTH_SHORT).show();
error.printStackTrace();
}
});
MySingleton.getmInstance(view.getContext()).addToRequestQueue(jsonObjectRequest;
return view;
}
And the MySingleton.java
public class MySingleton {
private static MySingleton mInstance;
private static Context ctx;
private RequestQueue requestQueue;
private MySingleton(Context ctx) {
this.ctx =ctx;
requestQueue = getRequestQueue();
}
private RequestQueue getRequestQueue() {
if(requestQueue == null) {
requestQueue = Volley.newRequestQueue(ctx.getApplicationContext());
}
return requestQueue;
}
public static synchronized MySingleton getmInstance(Context context) {
if(mInstance == null) {
mInstance = new MySingleton(context);
}
return mInstance;
}
public <T>void addToRequestQueue(Request<T> request){
getRequestQueue().add(request);
}
}

Try this:
Add this in your Singleton classs:
#Override
public void onCreate() {
super.onCreate();
// initialize the singleton
mInstance = this;
}
:
HashMap<String, String> params = new HashMap<>();
params.put("value","value" );
params.put("value", "value");
JSONObject par = new JSONObject(params);
JsonObjectRequest objectRequest = new JsonObjectRequest("url here", par,
new Response.Listener<JSONObject>()
{
#Override
public void onResponse(JSONObject response) {
Log.d(" response", response.toString());
}},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
//handle error here
}
});
// Access the RequestQueue through your singleton class.
MyApplication.getInstance().addToRequestQueue(jsObjRequest);
Let me know in the comments for any further queries

Related

Can't understand why it is onErrorResponse which is "Something went wrong"

I want to have answer on onResponse but did not get it. I need guidance how I can achieve this.
This is my code :
public class Network {
Context context;
String pokemondata;
CallbackInterface callbackInterface;
public Network(Context context,CallbackInterface callbackInterface) {
this.context = context;
this.callbackInterface=callbackInterface;
}
public void test(){
String URL = "http://pokeapi.co/api/v2/pokemon/";
RequestQueue requestQueue = Volley.newRequestQueue(context);
JsonObjectRequest jsonObjectRequest= new JsonObjectRequest(Request.Method.GET, URL, null,new Response.Listener<JSONObject>(){
#Override
public void onResponse(JSONObject response) {
Log.d("onResponse", String.valueOf(response));
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(context,"Something went wrong",Toast.LENGTH_SHORT).show();
callbackInterface.data("failure");
Log.d("fail","failure");
}
});
requestQueue.add(jsonObjectRequest);
}
}
failure - OnErrorResponse which prints com.example.tablayout D/Data: My data +failure
onResponse data is "http://pokeapi.co/api/v2/pokemon/"
I have used String url = "https://pokeapi.co/api/v2/pokemon/"; instead of String URL = "http://pokeapi.co/api/v2/pokemon/";
Now it's working

how do I make the data I input in the EditText inserted into the database and appear on the recyclerview without refreshing it like ajax?

I tried using adapter.notifyDataSetChanged() but failed, maybe someone could tell me where the code was placed.
This is my MainActivity:
private RecyclerView mList;
private LinearLayoutManager linearLayoutManager;
private DividerItemDecoration dividerItemDecoration;
private Adapter mExampleAdapter;
private ArrayList<Model> mExampleList;
private RecyclerView.Adapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
modelList = new ArrayList<>();
pesan= (EditText) findViewById(R.id.pesan);
user= 1;
admin= 1;
save = (ImageButton) findViewById(R.id.btn_submit);
mList = findViewById(R.id.main_list);
modelList = new ArrayList<>();
adapter = new Adapter(getApplicationContext(),modelList);
linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
dividerItemDecoration = new DividerItemDecoration(mList.getContext(), linearLayoutManager.getOrientation());
mList.setHasFixedSize(true);
mList.setLayoutManager(linearLayoutManager);
mList.setAdapter(adapter);
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final String isi_pesan = pesan.getText().toString();
final String id_admin = admin.toString();
final String id_user = user.toString();
RequestQueue queue = Volley.newRequestQueue(MainActivity.this);
StringRequest request = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
pesan.setText("");
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "my error :"+error, Toast.LENGTH_LONG).show();
Log.i("My error",""+error);
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> map = new HashMap<String, String>();
map.put("message",isi_pesan);
map.put("id_admin",id_admin);
map.put("id_user",id_user);
return map;
}
};
queue.add(request);
}
});
getData();
}
private void getData() {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Loading...");
progressDialog.show();
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
for (int i = 0; i < response.length(); i++) {
try {
JSONObject jsonObject = response.getJSONObject(i);
Model model = new Model();
model.setPesan(jsonObject.getString("isi_pesan"));
model.setAdmin(jsonObject.getString("sender"));
modelList.add(model);
adapter.notifyDataSetChanged();
mExampleAdapter = new Adapter(MainActivity.this, modelList);
mList.setAdapter(mExampleAdapter);
} catch (JSONException e) {
e.printStackTrace();
progressDialog.dismiss();
}
}
progressDialog.dismiss();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volley", error.toString());
progressDialog.dismiss();
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(jsonArrayRequest);
}
}
I want the data I post to appear in real time like whatsapp
First you told recyclerveiw that the number of items are fixed
mList.setHasFixedSize(true);
but in getData method you added an item to it.
second, don't call adapter.notifyDataSetChanged(); when you just added an item, instead call notifyItemInserted(position);
third, you replaced adapter after calling adapter.notifyDataSetChanged();, first replace adapter then call adapter.notifyDataSetChanged();

Activity cannot be cast to Interface (ClassCastException)

I'm currently getting a ClassCastException in my android app caused by "activity cannot be cast to interface".
Here is my code:
Logcat says the Exception is thrown in the onAttach part in MovieGridFragment on the line "this.clickListener = (clickInterfaceHelper) context;".
My Interface:
public interface clickInterfaceHelper {
void clickOnItem(int id);
void favoriteMovieItem(int movieId); }
The Fragment Class:
public class MovieGridFragment extends Fragment {
public clickInterfaceHelper clickListener;
private int index;
private GridView movieGridView;
public List<movieData> movieDataList = new ArrayList<>();
public MovieGridFragment() {} //empty constructor
#Override
public void onAttach(Context context) {
this.clickListener = (clickInterfaceHelper) context;
super.onAttach(context);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
if(savedInstanceState != null) {
if (!movieDataList.isEmpty()) {
movieDataList = Arrays.asList((movieData[]) savedInstanceState.getSerializable("OLDMOVIEDATA"));
}
}
super.onCreate(savedInstanceState);
}
The MainActivity:
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
View rootView = inflater.inflate(R.layout.movie_display_fragment, container, false);
movieGridView = (GridView) rootView.findViewById(R.id.gv_movie_display);
movieAdapter adapter = new movieAdapter(getActivity(),movieDataList);
adapter.notifyDataSetChanged();
movieGridView.setAdapter(adapter);
movieGridView.setSelection(index);
movieGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(clickListener != null)
clickListener.clickOnItem(position);
}
});
return rootView;
}
#Override
public void onSaveInstanceState(Bundle outState) {
index = movieGridView.getFirstVisiblePosition();
outState.putSerializable("OLDMOVIEDATA",movieData.movieDataArray);
super.onSaveInstanceState(outState);
}}
and mainactivity:
public class MainActivity extends AppCompatActivity implements clickInterfaceHelper {
public static String sorterString = null;
public static String urlBase = "https://api.themoviedb.org/3/movie/";
public static String urlFinal = null;
RequestQueue requestQueue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.activity_container, new MovieGridFragment())
.commit();
movieData.movieDataPosition = 0;
}
if(savedInstanceState != null) {
sorterString = savedInstanceState.getString("SORTER");
}
if(savedInstanceState == null)
movieData.movieDataPosition = 0;
if(sorterString==null)
sorterString="popular?";
if(sorterString!="favorite" && sorterString!=null) {
if(networkChecker.isNetworkAvailableChecker(this)) {
movieRequest();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu_act, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == R.id.m_popularity_action) {
if(sorterString != "popular?") {
sorterString = "popular?";
if(networkChecker.isNetworkAvailableChecker(this))
movieRequest();
}
return true;
}
if(id == R.id.m_action_voter) {
if(sorterString != "top_rated?") {
sorterString = "top_rated?";
if(networkChecker.isNetworkAvailableChecker(this))
movieRequest();
}
return true;
}
if(id == R.id.m_favorite_btn) {
if(sorterString != "favorite") {
SQLiteOpenHelper helper = new movieDataDbHelper(this);
SQLiteDatabase database = helper.getReadableDatabase();
Cursor cursor= database.query(movieDataContract.contractEntry.TABLE_NAME,
new String[] {
movieDataContract.contractEntry.ID,
movieDataContract.contractEntry.IMG_PATH},null,null,null,null,null);
if(cursor.getCount() == 0) {
Toast.makeText(this, "there are no favorite movies yet!",Toast.LENGTH_SHORT).show();
} else {
sorterString = "favorite";
showFavoriteFragment();
}
database.close();
helper.close();
cursor.close();
}
return true;
}
return super.onOptionsItemSelected(item);
}
public void showFavoriteFragment() {
favoriteMoviesDetailsFragment fragment = new favoriteMoviesDetailsFragment();
try {
getFragmentManager().beginTransaction().replace(R.id.activity_container,fragment).commit();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
outState.putString("SORTER", sorterString);
outState.putInt("POSITION",movieData.movieDataPosition);
super.onSaveInstanceState(outState, outPersistentState);
}
public void movieRequest() {
urlFinal = urlBase + sorterString + movieData.apiKey;
urlFinal.trim();
requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, urlFinal, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray array = response.getJSONArray("results");
movieData.movieDataArray = new movieData[array.length()];
for (int i = 0; i < array.length(); i++) {
movieData movie = new movieData();
JSONObject jsonObject = array.getJSONObject(i);
//movie.setPosition(i);
movie.setMovieId(jsonObject.getString("id"));
movie.setMovieImagePath(jsonObject.getString("poster_path"));
movie.setMovieTitle(jsonObject.getString("original_title"));
movie.setMoviePlot(jsonObject.getString("overview"));
movie.setMovieVoting(jsonObject.getString("vote_average"));
movie.setMovieReleaseDate(jsonObject.getString("release_date"));
movieData.movieDataArray[i] = movie;
}
MovieGridFragment gridFragment = new MovieGridFragment();
gridFragment.movieDataList = Arrays.asList(movieData.movieDataArray); //hier wird datalist eigentlich zugewiesen
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.activity_container, gridFragment);
try {
transaction.commitAllowingStateLoss();
} catch (Exception e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("volley", String.valueOf(error));
}
}
);
requestQueue.add(jsonObjectRequest);
}
#Override
public void clickOnItem(int id) {
movieData.movieDataPosition = id;
if(movieData.movieDataArray == null) {
movieRequest();
} else {
Intent intent = new Intent(this, detailsActivity.class);
intent.putExtra("FRAGMENT","MOVIE");
startActivity(intent);
}
}
#Override
public void favoriteMovieItem(int movieId) {
movieData.dbPosition = movieId;
Intent intent = new Intent(this,detailsActivity.class);
intent.putExtra("FRAGMENT","favorite");
startActivity(intent);
} }
You can try this
this.clickListener = (MainActivity) getActivity();
You get the FragmentActivity and cast it into your MainActivity
EDIT:
I suggest you to add a function in your fragment like :
public void setListener(clickInterfaceHelper listener) {
this.clickListener = listener;
}
And in your activity :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
MovieGridFragment fragment = new MovieGridFragment();
fragment.setListener(this); // some change here
getSupportFragmentManager().beginTransaction()
.add(R.id.activity_container, fragment)
.commit();
movieData.movieDataPosition = 0;
}
if(savedInstanceState != null) {
sorterString = savedInstanceState.getString("SORTER");
}
if(savedInstanceState == null)
movieData.movieDataPosition = 0;
if(sorterString==null)
sorterString="popular?";
if(sorterString!="favorite" && sorterString!=null) {
if(networkChecker.isNetworkAvailableChecker(this)) {
movieRequest();
}
}
}
.... no relevant functions
public void movieRequest() {
urlFinal = urlBase + sorterString + movieData.apiKey;
urlFinal.trim();
requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, urlFinal, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray array = response.getJSONArray("results");
movieData.movieDataArray = new movieData[array.length()];
for (int i = 0; i < array.length(); i++) {
movieData movie = new movieData();
JSONObject jsonObject = array.getJSONObject(i);
//movie.setPosition(i);
movie.setMovieId(jsonObject.getString("id"));
movie.setMovieImagePath(jsonObject.getString("poster_path"));
movie.setMovieTitle(jsonObject.getString("original_title"));
movie.setMoviePlot(jsonObject.getString("overview"));
movie.setMovieVoting(jsonObject.getString("vote_average"));
movie.setMovieReleaseDate(jsonObject.getString("release_date"));
movieData.movieDataArray[i] = movie;
}
MovieGridFragment gridFragment = new MovieGridFragment();
gridfragment.setListener(this); // some change here
gridFragment.movieDataList = Arrays.asList(movieData.movieDataArray); //hier wird datalist eigentlich zugewiesen
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.activity_container, gridFragment);
try {
transaction.commitAllowingStateLoss();
} catch (Exception e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("volley", String.valueOf(error));
}
}
);
requestQueue.add(jsonObjectRequest);
}
Hope this helps.
The context passed in is not necessarily your activity. It could be a wrapper around it with various theming and other overrides. You can never assume that when passed a Context, you're passed an Activity. If you need a reference to a click handler, write a setClickHandler function and call it explicitly.
Even if it is the Activity, the app doesn't know that- at that point its a Context. You'd need to explicitly cast it, which may not work (and may work on some versions of the OS and not others) due to paragraph 1.
Try to put your interface inside fragment class.
public class MovieGridFragment extends Fragment {
public clickInterfaceHelper clickListener;
private int index;
private GridView movieGridView;
public List<movieData> movieDataList = new ArrayList<>();
public MovieGridFragment() {} //empty constructor
#Override
public void onAttach(Context context) {
this.clickListener = (clickInterfaceHelper) context;
super.onAttach(context);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
if(savedInstanceState != null) {
if (!movieDataList.isEmpty()) {
movieDataList = Arrays.asList((movieData[]) savedInstanceState.getSerializable("OLDMOVIEDATA"));
}
}
super.onCreate(savedInstanceState);
}
public interface clickInterfaceHelper {
void clickOnItem(int id);
void favoriteMovieItem(int movieId);
}
}
To all android beginners, you can use the interface like below-mentioned way.
Define an Interface,
public interface CallBack {
String stringValue(String s);
}
In Fragment,
Callback mCallback;
In onAttach(Context context) method of your fragment,
mCallback = (Callback) context; // Casting to the activity
mcallback.stringValue("Your message");
Then in your Activity, you must implement the interface else you will get
classcastException
public class MainActivity implements CallBack{
#Override
public String stringValue(String s) {
// Here you will get the value from the fragment
return s;
}
}
It's not advisable to pass values between two fragments directly using interfaces. You should use the activity as a mediator while passing values.

How to save and restore custom arraylist on configuration change [duplicate]

This question already has answers here:
How to save custom ArrayList on Android screen rotate?
(4 answers)
Closed 6 years ago.
I have an ArrayList with custom json objects fetched from the web with Volley. I would like to be able to save and restore these objects on a screen rotate. I would also like to save and restore my current scrolled position on screen rotate.
I have a sketchy idea that this can be done with onSaveInstanceState and onRestoreInstanceState?
Activity Code
public class MainActivity extends AppCompatActivity {
private final String TAG = "MainActivity";
//Creating a list of posts
private List<PostItems> mPostItemsList;
//Creating Views
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
private ProgressDialog mProgressDialog;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "Device rotated and onCreate called");
//Initializing Views
recyclerView = (RecyclerView) findViewById(R.id.post_recycler);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
//Initializing the postlist
mPostItemsList = new ArrayList<>();
adapter = new PostAdapter(mPostItemsList, this);
recyclerView.setAdapter(adapter);
if (NetworkCheck.isAvailableAndConnected(this)) {
//Caling method to get data
getData();
} else {
final Context mContext;
mContext = this;
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(R.string.alert_titl);
alertDialogBuilder.setMessage(R.string.alert_mess);
alertDialogBuilder.setPositiveButton(R.string.alert_posi, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (!NetworkCheck.isAvailableAndConnected(mContext)) {
alertDialogBuilder.show();
} else {
getData();
}
}
});
alertDialogBuilder.setNegativeButton(R.string.alert_nega, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alertDialogBuilder.show();
}
}
//This method will get data from the web api
private void getData(){
Log.d(TAG, "getData called");
//Showing progress dialog
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setCancelable(false);
mProgressDialog.setMessage(this.getResources().getString(R.string.load_post));
mProgressDialog.show();
//Creating a json request
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(ConfigPost.GET_URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, "onResponse called");
//Dismissing the progress dialog
if (mProgressDialog != null) {
mProgressDialog.hide();
}
/*progressDialog.dismiss();*/
//calling method to parse json array
parseData(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
//Creating request queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
//Adding request to the queue
requestQueue.add(jsonArrayRequest);
}
//This method will parse json data
private void parseData(JSONArray array){
Log.d(TAG, "Parsing array");
for(int i = 0; i<array.length(); i++) {
PostItems postItem = new PostItems();
JSONObject jsonObject = null;
try {
jsonObject = array.getJSONObject(i);
postItem.setPost_title(jsonObject.getString(ConfigPost.TAG_POST_TITLE));
postItem.setPost_body(jsonObject.getString(ConfigPost.TAG_POST_BODY));
} catch (JSONException w) {
w.printStackTrace();
}
mPostItemsList.add(postItem);
}
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy called");
if (mProgressDialog != null){
mProgressDialog.dismiss();
Log.d(TAG, "mProgress dialog dismissed");
}
}
Thanks in advance.
Note a duplicate of How to save custom ArrayList on Android screen rotate?. While the arraylist in that question is declared in the Activity, mine is fetched with volley from the web. I don't know how to implement it for my arraylist, else this question wouldn't be asked
This is, in fact, a duplicate of the post you mentioned. Yes, the list was declared in the activity's onCreate() in that post, whereas you are doing it asynchronously. However, the idea is the same.
Once you have data to send, at any point of your application, it can be saved and restored.
The key, in your case, is to not call getData() every time the device is rotated. If you already have data loaded in mPostItemsList, then save and restore it via onSaveInstanceState(), and in onCreate() you get the data from the saved state. If that data does not exist, then you call getData().
public class MainActivity extends AppCompatActivity {
private final String TAG = "MainActivity";
private final String KEY_POST_ITEMS = "#postitems";
//Creating a list of posts
private List<PostItems> mPostItemsList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeViews();
if (savedInstanceState != null && savedInstanceState.containsKey(KEY_POST_ITEMS)){
mPostItemsList = savedInstanceState.getParcelableArrayList(KEY_POST_ITEMS);
} else {
//Initializing the postlist
mPostItemsList = new ArrayList<>();
if (NetworkCheck.isAvailableAndConnected(this)) {
//Caling method to get data
getData();
} else {
showNoNetworkDialog();
}
}
mAdapter = new PostAdapter(mPostItemsList, this);
recyclerView.setAdapter(adapter);
}
private void parseData(JSONArray array){
mPostItemsList.clear();
for(int i = 0; i<array.length(); i++) {
PostItems postItem = new PostItems();
JSONObject jsonObject = null;
try {
jsonObject = array.getJSONObject(i);
postItem.setPost_title(jsonObject.getString(ConfigPost.TAG_POST_TITLE));
postItem.setPost_body(jsonObject.getString(ConfigPost.TAG_POST_BODY));
} catch (JSONException w) {
w.printStackTrace();
}
mPostItemsList.add(postItem);
}
mAdapter.notifyDataSetchanged();
}
Edit: I didn't see the requirement to save scroll position. Look at Emin Ayar's answer for that. Also, a similar answer for it is also here: How to save recyclerview scroll position.
You can use onConfigurationChanged at your activity to detect rotation changes. Also you should track lastVisibleItemPosition with layoutManager.findLastVisibleItemPosition() and when rotation changed you should scroll to this position. You will need to use recyclerView.setOnScrollListener() to listen scrolls to keep your lastVisibleItemPosition updated
public class MainActivity extends AppCompatActivity {
private final String TAG = "MainActivity";
//Creating and initializing list of posts
private List<PostItems> mPostItemsList = new ArrayList<>();;
//Creating Views
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private RecyclerView.LayoutManager layoutManager;
private ProgressDialog mProgressDialog;
private int lastVisibleItemPos = -1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(TAG, "Device rotated and onCreate called");
if (NetworkCheck.isAvailableAndConnected(this)) {
//Caling method to get data and check if postList have value set before or not
// because this part will be called on every rotation change, we are controlling this
if (mPostItemsList.size() <= 0) {
//Initializing Views
recyclerView = (RecyclerView) findViewById(R.id.post_recycler);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
adapter = new PostAdapter(mPostItemsList, this);
recyclerView.setAdapter(adapter);
getData();
}
} else {
final Context mContext;
mContext = this;
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
alertDialogBuilder.setTitle(R.string.alert_titl);
alertDialogBuilder.setMessage(R.string.alert_mess);
alertDialogBuilder.setPositiveButton(R.string.alert_posi, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
if (!NetworkCheck.isAvailableAndConnected(mContext)) {
alertDialogBuilder.show();
} else {
getData();
}
}
});
alertDialogBuilder.setNegativeButton(R.string.alert_nega, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
finish();
}
});
alertDialogBuilder.show();
}
}
//This method will get data from the web api
private void getData(){
Log.d(TAG, "getData called");
//Showing progress dialog
mProgressDialog = new ProgressDialog(MainActivity.this);
mProgressDialog.setCancelable(false);
mProgressDialog.setMessage(this.getResources().getString(R.string.load_post));
mProgressDialog.show();
//Creating a json request
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(ConfigPost.GET_URL,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, "onResponse called");
//Dismissing the progress dialog
if (mProgressDialog != null) {
mProgressDialog.hide();
}
/*progressDialog.dismiss();*/
//calling method to parse json array
parseData(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
//Creating request queue
RequestQueue requestQueue = Volley.newRequestQueue(this);
//Adding request to the queue
requestQueue.add(jsonArrayRequest);
}
//This method will parse json data
private void parseData(JSONArray array){
Log.d(TAG, "Parsing array");
for(int i = 0; i<array.length(); i++) {
PostItems postItem = new PostItems();
JSONObject jsonObject = null;
try {
jsonObject = array.getJSONObject(i);
postItem.setPost_title(jsonObject.getString(ConfigPost.TAG_POST_TITLE));
postItem.setPost_body(jsonObject.getString(ConfigPost.TAG_POST_BODY));
} catch (JSONException w) {
w.printStackTrace();
}
mPostItemsList.add(postItem);
}
}
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// set your adapter here with your data
adapter = new PostAdapter(mPostItemsList, this);
recyclerView.setAdapter(adapter);
}
#Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy called");
if (mProgressDialog != null){
mProgressDialog.dismiss();
Log.d(TAG, "mProgress dialog dismissed");
}
}

Why is my JsonObjectRequest not working?

I have been fiddling with this for a few days now. Couldn't get it right. Android studio won't let me compile it with this error. So, I have this application where I have two tabs and two fragments. One fragment is called new, and that fragment fetches json. But I couldn't get to do it properly. I have uploaded a picture of how the error looks like, and the class files. Can you please help me out?
Error: "Cannot resolve constructor JsonObjectRequest(int, java.lang.String, null.......)
new_fragment.java
public class new_fragment extends Fragment {
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
private String mParam1;
private String mParam2;
private VolleySingleton volleySingleton;
private ImageLoader imageLoader;
private RequestQueue requestQueue;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() !=null){
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
volleySingleton = VolleySingleton.getsInstance();
requestQueue = volleySingleton.getRequestQueue();
RequestQueue requestQueue = VolleySingleton.getsInstance().getRequestQueue();
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET,"http://10.0.8.152/json/new.json",null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(request);
}
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedIntanceState) {
setHasOptionsMenu(true);
View layout = inflater.inflate(R.layout.new_fragment, container, false);
return layout;
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// TODO Auto-generated method stub
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.ref_menu, menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// handle item selection
switch (item.getItemId()) {
case R.id.refreshico:
// do s.th.
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
VolleySingleton
public class VolleySingleton {
private static VolleySingleton sInstance = null;
private ImageLoader mImageLoader;
private RequestQueue mRequestQueue;
private VolleySingleton(){
mRequestQueue = Volley.newRequestQueue(appClass.getAppContext());
mImageLoader = new ImageLoader(mRequestQueue,new ImageLoader.ImageCache() {
private LruCache<String, Bitmap> cache = new LruCache<>((int)(Runtime.getRuntime().maxMemory()/1024)/8);
#Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
#Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url, bitmap);
}
});
}
public static VolleySingleton getsInstance(){
if(sInstance==null){
sInstance = new VolleySingleton();
}
return sInstance;
}
public RequestQueue getRequestQueue(){
return mRequestQueue;
}
public ImageLoader getImageLoader(){
return mImageLoader;
}
}
cast (String)null.
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET,"http://10.0.8.152/json/new.json",(String)null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
new JsonObjectRequest takes 3rd Parameter as String requestBody
cast null to String
or you can make a null string like String rBody = null; and then pass rBody as 3rd Parameter
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET,
"http://10.0.8.152/json/new.json", (String) null, // here
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(request);
For everyone trying to implement this right now: Google changed the jsonObjectRequest constructor: now you don't suppy the request type anymore, instead you supply firstly the url and then null as second parameter if you want a get request. e.g.:
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest("http://www.aaa.com/getJSON/dummyMeldung.json", null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray jsonArray = response.getJSONArray("meldung");
for (int i = 0; i <= jsonArray.length(); i++) {
JSONObject meldung = jsonArray.getJSONObject(i);
String comment = meldung.getString("comment");
Log.d("ausgabe", comment);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
Well, i see the situation, and it happends because as your error say, the constructor doesnt exists.
If you are using the JsonObjectRequest as default, and you want to consume an Get method, you dont have to send the null parameter, you just should send of this way:
Change this:
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET,"http://10.0.8.152/json/new.json",null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(request);
For this:
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET,"http://10.0.8.152/json/new.json",
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
requestQueue.add(request);
As you can see, i just remove the parameter for the JsonObject, because the method is Get, and there is an constructor thats accept that you dont send JsonObject.
Another solution is to make your own JsonObjectRequest, and custom it to accept that kind of values.
Regards.
There is a ambiguous Constructor, for solve this, use this code:
JSONObject jsonObject = null;
JsonObjectRequest request = new JsonObjectRequest(
Request.Method.GET, "Your url", jsonObject,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
The problem as to do with the version of volley.
On your build.gradle app file you should have
dependencies {
......
compile 'com.mcxiaoke.volley:library:1.0.0'
.....
}

Categories