I tried to fetch the json values from url and shows in listview with adapter in recylerview. but the listview is empty and getting this error 'No adapter attached; skipping layout'. When I tried with the below code its working
for (int i = index; i < end; i++) {
User user = new User();
user.setName("Name " + i);
mUsers.add(user);
}
Here is my part of code, if needed I'll upload complete code
public class OtherNews extends AppCompatActivity {
JSONArray jsonarray;
private RecyclerView mRecyclerView;
private List<User> mUsers = new ArrayList<>();
private UserAdapter mUserAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
mRecyclerView = (RecyclerView) findViewById(R.id.recycleView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
mUserAdapter = new UserAdapter();
new DownloadJSON().execute();
mUserAdapter.setOnLoadMoreListener(new OnLoadMoreListener() {
#Override
public void onLoadMore() {
Log.e("haint", "Load More");
mUsers.add(null);
mUserAdapter.notifyItemInserted(mUsers.size() - 1);
//Load more data for reyclerview
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Log.e("haint", "Load More 2");
//Remove loading item
mUsers.remove(mUsers.size() - 1);
mUserAdapter.notifyItemRemoved(mUsers.size());
//Load data
int index = mUsers.size();
int end = index + 20;
for (int i = index; i < end; i++) {
User user = new User();
user.setName("Name " + i);
user.setEmail("alibaba" + i + "#gmail.com");
mUsers.add(user);
}
mUserAdapter.notifyDataSetChanged();
mUserAdapter.setLoaded();
}
}, 5000);
}
});
}
// DownloadJSON AsyncTask
private class DownloadJSON extends AsyncTask<Void, Void, Void> {
private static final String TAG = "";
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
// Create an array
HttpHandler sh = new HttpHandler();
// Making a request to url and getting response
String jsonStr = sh.makeServiceCall("http://xxxxxxxxx.in/projects/falcon/getallnews.php?page=2");
if (jsonStr != null) {
try {
JSONObject jsonobject = new JSONObject(jsonStr);
jsonarray = jsonobject.getJSONArray("news");
// Getting JSON Array node
for (int i = 0; i < jsonarray.length(); i++) {
User user = new User();
String title = jsonobject.getString("title");
user.setName(title);
mUsers.add(user);
}
} catch (final JSONException e) {
}
} else {
Log.d(TAG, "someOther)");
}
return null;
}
#Override
protected void onPostExecute(Void args) {
mRecyclerView.setAdapter(mUserAdapter);
}
}
I get the value in this line of code, but couldn't set in list view.
String title = jsonobject.getString("title");
user.setName(title);
The issue is exactly like it sounds, an adapter is not being attached when it needs it. You don't attach it until onPostExecute. Just attach it right from the beginning:
mRecyclerView = (RecyclerView) findViewById(R.id.recycleView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
mUserAdapter = new UserAdapter();
mRecyclerView.setAdapter(mUserAdapter);
As you modify the adapter in other parts of the code, your RecyclerView will update automatically, so long as you call notifyDataSetChanged() or some related method.
Related
I am developing an android app, where I am using Relam as local Database. I have rest api one for all the user information and other is for news information. I have two buttons. one for showing the user information and other is for showing the news information. Now, with my code what is done, after login, I need to click the button at first for user information and news information accordingly and then I can see those images and news. but if I connection off, just after login, the data is not showing in the view. I am explaining my code in detail.Also I am having problem in image loading. How can I Make the funtionality so that user can get all the information just after login.I am reallly sorry for such a long code. It would be really helpful for me if someone tell me how can I modify my code to store all data in background thread, so that user get all information just after login.
The part of the login page where I want to start
private void loginUser(final String mEmail, final String mPassword) {
final GlobalClass globalClass = new GlobalClass();
globalClass.setEmail_info( mEmail );
setFilePath();
RequestQueue queue = Volley.newRequestQueue( LoginPage.this );
StringRequest strReq = new StringRequest( Request.Method.POST,
LOGIN_URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d( TAG, "Register Response: " + response.toString() );
//parse your response here
if (response.contains( "overview" )) {
showProgress( true );
globalClass.setImage_urlpath( Constants.HTTP.PHOTO_URL + mEmail);
String str = globalClass.readDatafromStorage();
Log.d("----After Login---",str);
if ( !str.contains("ACTIVATE") ) {
Log.d( "----After Login---", "After Login" );
}
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putString(KEY_EMAIL, mEmail);
editor.putString(KEY_PASSWORD, mPassword);
editor.commit();
showProgress(false);
Intent loginIntent = new Intent(LoginPage.this, MainOptionPage.class);
loginIntent.putExtra(KEY_EMAIL, mEmail);
startActivity(loginIntent);
} else {
userEmail.setError(getString(R.string.error_incorrect_login));
userEmail.requestFocus();
}
}
}, new Response.ErrorListener() {
#Override
....
Here is my code for User Page
public class MyColleaguesPage extends AppCompatActivity implements ColleagueController.UserCallbackListener {
private List<MyColleagueModel> myColleagueList = new ArrayList<>();
private Realm colleagueRealm;
private RealmResults<MyColleagueModel> colleagueResult;
private List<MyColleagueModel> filteredModelList;
private RealmChangeListener realmListener;
private static final String DIALOG_TAG = "EmployeeDialog";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mycolleagues_layout);
configViews();
}
private void configViews() {
recyclerView = this.findViewById(R.id.colleagues_recycler);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(MyColleaguesPage.this));
recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
colleagueRealm = Realm.getDefaultInstance();
RealmResults<MyColleagueModel> results = colleagueRealm.where(MyColleagueModel.class).findAll();
for (int i = 0; i < results.size(); i++) {
myColleagueList.add(results.get(i));
}
adapter = new MyColleaguesAdapter(myColleagueList,getApplicationContext());
//adapter = new MyColleaguesAdapter(myColleagueList,getApplicationContext());
Log.d( "adapter value is"+"", String.valueOf( adapter ) );
recyclerView.setAdapter(adapter);
}
//successful
#Override
public void onFetchStart() {
}
#Override
public void onFetchProgress(ColleagueModel colleague) {
//adapter.addColleague(colleague);
}
#Override
public void onFetchProgress(List<ColleagueModel> colleagueList) {
}
#Override
public void onFetchComplete() {
}
#Override
public void onFetchFailed() {
}
}
Here is my controller class for my colleague page
public class ColleagueController {
private static final String TAG = ColleagueController.class.getSimpleName();
private UserCallbackListener mListener;
private ColleagueResApiManager mApiManager;
Realm myColleague_realm;
public ColleagueController() {
mApiManager = new ColleagueResApiManager();
}
public void startFetching(){
myColleague_realm = Realm.getDefaultInstance();
mApiManager.getColleagueApi().getColleague(new Callback<String>() {
#Override
public void success(String s, Response response) {
Log.d(TAG, "JSON :: " + s);
try {
JSONArray array = new JSONArray(s);
for(int i = 0; i < array.length(); i++) {
JSONObject object = array.getJSONObject(i);
Log.d("-----Start Fetching---", object.optString( "name" ));
myColleague_realm.beginTransaction();
MyColleagueModel mycolleague = myColleague_realm.createObject( MyColleagueModel.class );
mycolleague.setName( object.optString( "name" ) );
.... data ) );
myColleague_realm.commitTransaction();
}
} catch (JSONException e) {
mListener.onFetchFailed();
}
// mListener.onFetchComplete();
}
#Override
public void failure(RetrofitError error) {
Log.d(TAG, "Error :: " + error.getMessage());
if (mListener != null) {
mListener.onFetchComplete();
}
}
});
}
public interface UserCallbackListener{
void onFetchComplete();
void onFetchFailed();
}
}
In the same way I have other page news option page where I am shoing the news data. Here is my news page.
public class NewsPage extends AppCompatActivity{
private RecyclerView recyclerView;
private NewsAdapter adapter;
private Realm newsRealm;
private List<NewsRealmModel> mNewsList;
private List<NewsRealmModel> filteredModelList;
private NewsController mController;
Constant constant;
SharedPreferences app_preferences;
int appTheme;
int themeColor;
int appColor;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView( R.layout.news_page_layout);
configViews();
}
private void configViews() {
recyclerView = this.findViewById(R.id.news_recycler);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(NewsPage.this));
recyclerView.setRecycledViewPool(new RecyclerView.RecycledViewPool());
Realm newsRealm = Realm.getDefaultInstance();
RealmResults<NewsRealmModel> temp = newsRealm.where(NewsRealmModel.class).findAll();
mNewsList = new ArrayList<>();
for (int i = 0; i < temp.size(); i++) {
mNewsList.add(temp.get(i));
}
adapter = new NewsAdapter(mNewsList,getApplicationContext());
Log.d( "adapter value is"+"", String.valueOf( adapter ) );
recyclerView.setAdapter(adapter);
}
}
And the new Controller Class
public class NewsController {
private static final String TAG = NewsController.class.getSimpleName();
private UserCallbackListener mListener;
private NewsRestApiManager mApiManager;
private AppImage appImages;
Realm myNews_realm;
ArrayList<String> title_list = new ArrayList<>();
GlobalClass globalClass = new GlobalClass();
public NewsController(UserCallbackListener listener) {
mListener = listener;
mApiManager = new NewsRestApiManager();
}
public void startFetching() {
myNews_realm = Realm.getDefaultInstance();
mApiManager.getNewsApi().getNews(new Callback<String>() {
#Override
public void success(String s, Response response) {
Log.d(TAG, "JSON :: " + s);
try {
JSONArray array = new JSONArray(s);
for (int i = 0; i < array.length(); i++) {
JSONObject jsonObject = array.getJSONObject(i);
Log.d("-----Start Fetching---", jsonObject.optString("title"));
if (!myNews_realm.isInTransaction()) {
myNews_realm.beginTransaction();
NewsRealmModel news = new NewsRealmModel();
....... data
}
myNews_realm.copyToRealm(news);
myNews_realm.commitTransaction();
mListener.onFetchProgressNews(news);
} else {
myNews_realm.commitTransaction();
}
}
} catch (JSONException e) {
mListener.onFetchFailed();
}
mListener.onFetchComplete();
}
#Override
public void failure(RetrofitError error) {
Log.d(TAG, "Error :: " + error.getMessage());
mListener.onFetchComplete();
}
});
}
public interface UserCallbackListener {
void onFetchProgressNews(NewsRealmModel news);
void onFetchComplete();
void onFetchFailed();
}
}
To do your database processing on a background thread using Volley, you need to extend Request<T> and do the Realm write in parseNetworkResponse method.
public class RealmGsonObjectRequest<T, M extends RealmModel> extends Response<Void> {
...
#Override
protected Response<Void> parseNetworkResponse(
NetworkResponse response) {
try {
String json = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
T data = gson.fromJson(json, clazz);
// write the downloaded data into the Realm on bg thread
try(Realm r = Realm.getDefaultInstance()) {
M model = mapper.toModel(data);
r.executeTransaction((realm) -> {
realm.insertOrUpdate(model);
});
}
return Response.success(null,
HttpHeaderParser.parseCacheHeaders(response)
);
} // handle errors
}
You might need a RealmGsonListRequest as well.
public class RealmGsonListRequest<T, M extends RealmModel> extends Response<Void> {
...
#Override
protected Response<Void> parseNetworkResponse(
NetworkResponse response) {
try {
String json = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
List<T> data = gson.fromJson(json, new TypeToken<ArrayList<T>>() {}.getType());
// write the downloaded data into the Realm on bg thread
try(Realm r = Realm.getDefaultInstance()) {
M model = mapper.toModel(data);
r.executeTransaction((realm) -> {
realm.insertOrUpdate(model);
});
}
return Response.success(null,
HttpHeaderParser.parseCacheHeaders(response)
);
} // handle errors
}
For more information, refer to the official Volley tutorial on how to create a custom Volley request type.
im trying to get data from a server inform of JSON and im storing the data to my offline database ( in this case : Realm ), whenever i try to retrieve the data, nothing is displayed in the listview.
public class MainActivity extends AppCompatActivity {
public static ListView myList;
public static ListAdapter myAdapter;
public static Realm realm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Realm.init(this);
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmResults<Recipe> dRecipies = realm.where(Recipe.class).findAll();
if(dRecipies!= null)dRecipies.deleteAllFromRealm();
}
});
DownloadTask newTask = new DownloadTask();
newTask.execute("hi");
setContentView(R.layout.activity_main);
myList = (ListView) findViewById(R.id.Recipe_list);
// getData();
setDisplay();
myList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String p = String.valueOf(position);
Intent in = new Intent(MainActivity.this, SecondScreenDetails.class);
in.putExtra("Position", p);
startActivity(in);
}
});
}
public void setDisplay(){
ArrayList<Recipe> finalRecipies = new ArrayList<>();
RealmResults<Recipe> rrRecipies = realm.where(Recipe.class).findAll();
for(Recipe r: rrRecipies){
finalRecipies.add(r);
Toast.makeText(this, r.getName(), Toast.LENGTH_SHORT).show();
}
myAdapter = new ListViewAdapter(this, finalRecipies);
myList.setAdapter(myAdapter);
}
#Override
protected void onDestroy() {
realm.close();
super.onDestroy();
}
}
im doing this because, if i dont, the data keeps getting repeatedly stored, resulting in repetition.
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
RealmResults<Recipe> dRecipies = realm.where(Recipe.class).findAll();
if(dRecipies!= null)dRecipies.deleteAllFromRealm();
}
});
when i tried without actually deleting the data, then the Toast in the
setDisplay() method is working and the data is being shown.(Toasts are repeated as i open the app second time, it gets twice... etc)
When i insert this, even the toasts dont show up.
My download activity
public class DownloadTask extends AsyncTask<String,Void,String> {
private RealmList<Recipe> realmRecipe = new RealmList<>();
String result;
#Override
protected String doInBackground(String... params) {
result = "";
Realm realm = null;
realm = Realm.getDefaultInstance();
realm.executeTransaction(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("https://d17h27t6h515a5.cloudfront.net/topher/2017/May/59121517_baking/baking.json").build();
try {
result = client.newCall(request).execute().body().string();
Log.i("RESULT", result);
JSONArray rootArray = new JSONArray(result);
for (int i = 0; i < rootArray.length(); i++) {
JSONObject tempObject = rootArray.getJSONObject(i);
JSONArray jIngredients = tempObject.getJSONArray("ingredients");
JSONArray jSteps = tempObject.getJSONArray("steps");
// Get the ingredients
List<Ingredients> ingredients = new ArrayList<>();
for (int j = 0; j < jIngredients.length(); j++) {
JSONObject tempIngredient = jIngredients.getJSONObject(j);
Ingredients nIngredient = realm.createObject(Ingredients.class);
nIngredient.setIngredient(tempIngredient.getString("ingredient"));
nIngredient.setMeasure(tempIngredient.getString("measure"));
nIngredient.setQuantity(tempIngredient.getString("quantity"));
// Ingredients newIngredient = new Ingredients(tempIngredient.getString("quantity"),
// tempIngredient.getString("measure"),
// tempIngredient.getString("ingredient"));
// ingredients.add(newIngredient);
ingredients.add(nIngredient);
}
// Get the steps
List<Steps> steps = new ArrayList<>();
for (int j = 0; j < jSteps.length(); j++) {
JSONObject tempStep = jSteps.getJSONObject(j);
Steps nStep = realm.createObject(Steps.class);
nStep.setDescription(tempStep.getString("description"));
nStep.setId(tempStep.getString("id"));
nStep.setShortDescription(tempStep.getString("shortDescription"));
nStep.setVideoURL(tempStep.getString("videoURL"));
steps.add(nStep);
// Steps newStep = new Steps(tempStep.getString("id"), tempStep.getString("shortDescription"),
// tempStep.getString("description"), tempStep.getString("videoURL"));
// steps.add(newStep);
}
// Create the recipe
Recipe nRecipe = realm.createObject(Recipe.class);
nRecipe.setId(tempObject.getString("id"));
nRecipe.setName(tempObject.getString("name"));
nRecipe.setServings(tempObject.getString("servings"));
nRecipe.setIngredients(ingredients);
nRecipe.setSteps(steps);
realmRecipe.add(nRecipe);
// Recipe newRecipe = new Recipe(tempObject.getString("id"), tempObject.getString("name"), tempObject.getString("servings"), ingredients, steps);
// MainActivity.mRecipies.add(newRecipe);
}
}catch (Exception e){
Log.i("Error Message", e.getMessage());
}
}
});
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}
Here in my UI, i have used two buttons to load different data to a RecyclerView. First time the data is displaying properly on click of each button. But if i click the button for the second time the data is adding to the adapter twice. I mean the the adapter is not cleared. it is keep on adding the data on click of button. I Think i have to do something with the adapter on click of a button. Can anyone pls let me know how to clear the adapter or where i am going wrong..
Here is the code.
public class GstVendorLocRetrieve extends AppCompatActivity {
private String vault;
private TextView txt;
public static final String DATA_URL = "http://oursite.com/getgstvendorlocation.php?vault_no=";
public static final String DATA_URL1 = "http://oursite.com/getgstcustomerlocation.php?vault_no=";
//Tags for my JSONRes
public static final String TAG_VendorID = "VendorID";
public static final String TAG_CustomerID = "Customer_ID";
public static final String TAG_ADDRESS = "Address";
private Button vendor;
private Button customer;
//Creating a List of superheroes
private List<GstVendLoc> listSuperHeroes;
private List<GstCustLoc> listSuperHeroes1;
//Creating Views
private RecyclerView recyclerView;
private RecyclerView.LayoutManager layoutManager;
private RecyclerView.Adapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.locationretrieve);
SharedPreferences sharedPreferences = getSharedPreferences(GstLogin.SHARED_PREF_NAME, MODE_PRIVATE);
vault = sharedPreferences.getString(GstLogin.EMAIL_SHARED_PREF,"Not Available");
vendor = (Button) findViewById(R.id.login);
customer = (Button) findViewById(R.id.login1);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
//Initializing our superheroes list
listSuperHeroes = new ArrayList<>();
listSuperHeroes1 = new ArrayList<>();
vendor.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
recyclerView.setAdapter(null);
getData();
}
});
customer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
recyclerView.setAdapter(null);
getData1();
}
});
}
//This method will get data from the web api
private void getData(){
//Showing a progress dialog
final ProgressDialog loading = ProgressDialog.show(this,"Loading Data", "Please wait...",false,false);
//Creating a json array request
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(DATA_URL+vault,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
//Dismissing progress dialog
loading.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){
for(int i = 0; i<array.length(); i++) {
GstVendLoc gst1 = new GstVendLoc();
JSONObject json = null;
try {
json = array.getJSONObject(i);
gst1.setVendorID(json.getString(TAG_VendorID));
gst1.setAddress(json.getString(TAG_ADDRESS));
} catch (JSONException e) {
e.printStackTrace();
}
listSuperHeroes.add(gst1);
}
//Finally initializing our adapter
adapter = new CardAdapter17(listSuperHeroes, this);
//Adding adapter to recyclerview
recyclerView.setAdapter(adapter);
}
private void getData1(){
//Showing a progress dialog
final ProgressDialog loading = ProgressDialog.show(this,"Loading Data", "Please wait...",false,false);
//Creating a json array request
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(DATA_URL1+vault,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
//Dismissing progress dialog
loading.dismiss();
//calling method to parse json array
parseData1(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 parseData1(JSONArray array){
for(int i = 0; i<array.length(); i++) {
GstCustLoc gst1 = new GstCustLoc();
JSONObject json = null;
try {
json = array.getJSONObject(i);
gst1.setCustomer_ID(json.getString(TAG_CustomerID));
gst1.setAddress(json.getString(TAG_ADDRESS));
} catch (JSONException e) {
e.printStackTrace();
}
listSuperHeroes1.add(gst1);
}
//Finally initializing our adapter
adapter = new CardAdapter18(listSuperHeroes1, this);
//Adding adapter to recyclerview
recyclerView.setAdapter(adapter);
}
}
Use this code for clear RecycleView items
public void clear() {
int size = listSuperHeroes.size();
listSuperHeroes.clear();
notifyItemRangeRemoved(0, size);
}
You need to clear your Array List before you get data second time.
Do this inside parseData1 method before for loop.
listSuperHeroes.clear();
listSuperHeroes1.clear();
What you have to do is Update RecyclerView on button Click , Put below method in your adapter
public void updateData(ArrayList<ViewModel> viewModels) {
items.clear();
items.addAll(viewModels);
notifyDataSetChanged();
}
Than call this method with new data
ArrayList<ViewModel> viewModelsWithNewData = new ArrayList<ViewModel>();
adapter.updateData(viewModelsWithNewData );
you dont need to set adapter after geting data from the online
//Finally initializing our adapter
adapter = new CardAdapter18(listSuperHeroes1, this);
//Adding adapter to recyclerview
recyclerView.setAdapter(adapter);
you can initialize of set the adapter in the on create and add data in the 'listSuperHeroes1' and after parse data you can do adapter.notifyDataSetChanged();
this will change the list data.
and the solution for the getting the previous data you have to remove the all data from the listsuperHeroes1 this will help you if you getting any problem please comment .
I am just improving #Rony's answer.
If you should always check if the ArrayList is not null before attempting to call .size(), otherwise, you might end up with a null pointer exception
if (listSuperHeroes != null && !listSuperHeroes.isEmpty()) {
int size = listSuperHeroes.size();
listSuperHeroes.clear();
notifyItemRangeRemoved(0, size);
}
I want develop android application for one website. I read website posts from json and show its in RecyclerView every 10 posts and when user scrolling on RecyclerView show more 10 post and go to end! in this project i use okHTTP v3 and RecyclerView!
Json link : JSON LINK
I can load first 10 posts. i want when scrolling on RecyclerView show next 10 post, but show me again first 10 post!
MainActivity codes:
public class Main_page extends AppCompatActivity {
private static final long RIPPLE_DURATION = 250;
private Toolbar toolbar;
private RelativeLayout root;
private ImageView menu_image;
private RecyclerView main_recyclerView;
private MainAdapter2 mAdaper;
private List<MainDataModel> dataModels = new ArrayList<MainDataModel>();
private List<MainDataModel> dataModelsArray;
private Context context;
protected Handler handler;
private RelativeLayout loadLayout;
private LinearLayoutManager mLayoutManager;
private int pageCount = 1;
private String ServerAddress = ServerIP.getIP();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_page);
if (!EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().register(this);
}
handler = new Handler();
context = getApplicationContext();
loadLayout = (RelativeLayout) findViewById(R.id.main_empty_layout);
toolbar = (Toolbar) findViewById(R.id.main_toolbar);
if (toolbar != null) {
setSupportActionBar(toolbar);
getSupportActionBar().setTitle(null);
}
LoadData(pageCount);
mLayoutManager = new LinearLayoutManager(this);
// Menu
root = (RelativeLayout) findViewById(R.id.main_root);
View guillotineMenu = LayoutInflater.from(this).inflate(R.layout.menu_layout, null);
root.addView(guillotineMenu);
menu_image = (ImageView) toolbar.findViewById(R.id.toolbar_logo);
new GuillotineAnimation.GuillotineBuilder(guillotineMenu, guillotineMenu.findViewById(R.id.menu_layout_image), menu_image)
.setStartDelay(RIPPLE_DURATION)
.setActionBarViewForAnimation(toolbar)
.setClosedOnStart(true)
.build();
// RecyclerView and setData
main_recyclerView = (RecyclerView) findViewById(R.id.main_recycler);
main_recyclerView.setHasFixedSize(true);
main_recyclerView.setLayoutManager(mLayoutManager);
mAdaper = new MainAdapter2(this, main_recyclerView, dataModels);
main_recyclerView.setAdapter(mAdaper);
mAdaper.setOnLoadMoreListener(new OnLoadMoreListener() {
#Override
public void onLoadMore() {
dataModels.add(null);
mAdaper.notifyItemInserted(dataModels.size() - 1);
LoadData(pageCount);
}
});
}
#Subscribe
public void onEvent(List<MainDataModel> mainInfoModels) {
if (dataModels.size() > 0) {
dataModels.remove(dataModels.size() - 1);
mAdaper.notifyItemRemoved(dataModels.size());
mAdaper.setLoaded();
}
mAdaper.add(mainInfoModels);
mAdaper.notifyDataSetChanged();
++pageCount;
if (dataModels.isEmpty()) {
main_recyclerView.setVisibility(View.GONE);
loadLayout.setVisibility(View.VISIBLE);
} else {
main_recyclerView.setVisibility(View.VISIBLE);
loadLayout.setVisibility(View.GONE);
}
}
private void LoadData(int pageNumber) {
MainDataInfo dataInfo = new MainDataInfo();
// here getMainDataInfo() should return the server response
dataInfo.getMainDataInfo(this, pageNumber);
}
}
AsyncTask code:
public class MainDataInfo {
private Context mContext;
private String ServerAddress = ServerIP.getIP();
public void getMainDataInfo(Context context, int pageNumber) {
mContext = context;
new getInfo().execute(ServerAddress + "page=" + pageNumber);
}
private class getInfo extends AsyncTask<String, Void, String> {
EventBus bus = EventBus.getDefault();
private String ou_response;
private List<MainDataModel> infoModels;
#Override
protected void onPreExecute() {
CustomProcessDialog.createAndShow(mContext);
infoModels = new ArrayList<>();
}
#Override
protected String doInBackground(String... params) {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(ServerAddress + "page=1")
.cacheControl(CacheControl.FORCE_NETWORK)
.build();
Response response;
try {
response = client.newCall(request).execute();
ou_response = response.body().string();
response.body().close();
if (ou_response != null) {
try {
JSONObject postObj = new JSONObject(ou_response);
JSONArray postsArray = postObj.optJSONArray("posts");
infoModels = new ArrayList<>();
for (int i = 0; i <= infoModels.size(); i++) {
JSONObject postObject = (JSONObject) postsArray.get(i);
JSONObject images = postObject.optJSONObject("thumbnail_images");
JSONObject imagesPair = images.optJSONObject("medium");
int id = postObject.getInt("id");
String title = postObject.getString("title");
String content = postObject.getString("content");
String thumbnail = imagesPair.getString("url");
Log.d("Data", "Post id: " + id);
Log.d("Data", "Post title: " + title);
Log.d("Data", "Post title: " + thumbnail);
//Use the title and id as per your requirement
infoModels.add(new MainDataModel(id, title, content, thumbnail));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
return ou_response;
}
#Override
protected void onPostExecute(String result) {
CustomProcessDialog.dissmis();
if (result != null) {
bus.post(infoModels);
}
}
}
}
How can show next 10 post when scrolling on RecyclerView instance of show again first 10 post?
I checked your JSON , and when you increase page number there is no result. Please fix it first to show your results in your app.
While this one returning you 10 post
When you set your page number 2 , it is not returning any post, this is why you are seeing everytime first 10 post.
Hope it helps.
You will have to make different pages. One page have data of only 10 blogs. To get information about, Request JSON fro next page when 10th item is shown.
To get item shown info you can use layoutManager.findLastVisbleItem() or lastComletlyVisibleItem().
once requested data is downloaded. There must be method like onRequestComleted() in Volley. notifysetChanged there.
How can i pass the position of item using intent to start a new activity?
I want to start a new activity called single which displays the rating of the movie correspondingly..pls help
I have been trying this for the past two days.
Here is the code:
public class NowPlaying extends Fragment {
private static final String TAG = NowPlaying.class.getSimpleName();
// Movies json url
private static final String url = "http://private-8149-themoviedb.apiary-mock.com/3/movie/now_playing?api_key=";
private ProgressDialog pDialog;
private List<NowPlayingInfo> bottom = new ArrayList<NowPlayingInfo>() ;
NowPlayingAdapter adapter;
RecyclerView recyclerView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_main, container, false);
ActionBar toolbar = ((AppCompatActivity) getActivity()).getSupportActionBar();
toolbar.setTitle("Now playing");
recyclerView = (RecyclerView) v.findViewById(R.id.cardList);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(linearLayoutManager);
adapter = new NowPlayingAdapter(getActivity(), bottom);
recyclerView.setAdapter(adapter);
pDialog = new ProgressDialog(getActivity());
pDialog.setMessage("Loading...");
pDialog.show();
adapter.SetOnItemClickListener(new NowPlayingAdapter.OnItemClickListener() {
#Override
public void onItemClick(View v, int position) {
// do something with position
Intent i = new Intent(v.getContext(), Single.class);
//pass the position of the item to single class
v.getContext().startActivity(i);
}
});
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d(TAG, response.toString());
hidePDialog();
try {
JSONArray jsonArray = response.getJSONArray("results");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
NowPlayingInfo trailer = new NowPlayingInfo();
trailer.setTitle(jsonObject.getString("original_title"));
String iss = "http://image.tmdb.org/t/p/w500" + jsonObject.getString("poster_path") ;
trailer.setImage(iss);
bottom.add(trailer);
adapter.notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
hidePDialog();
}
});
AppController.getInstance().addToRequestQueue(jsonObjectRequest);
return v;
}
#Override
public void onDestroy() {
super.onDestroy();
hidePDialog();
}
private void hidePDialog() {
if (pDialog != null) {
pDialog.dismiss();
pDialog = null;
}
}
}
adapter.SetOnItemClickListener(new NowPlayingAdapter.OnItemClickListener() {
#Override
public void onItemClick(View v, int position) {
NowPlayingInfo _nowPlaying = bottom.get(position);
// do something with position
Intent i = new Intent(v.getContext(), Single.class);
//pass the position of the item to single class
i.putExtra("ISS", _nowPlaying.getImage()); //you can put your current playing info.
i.putExtra("POSITION", position); //you can put your position to next activity.
v.getContext().startActivity(i);
}
});
Add this in your SingleInfo Class.
String _rating = "";
public String get_rating() {
return _rating;
}
public void set_rating(String _rating) {
this._rating = _rating;
}
Add this in your Single class -
int _currentPos = 0 ; //Global variable .
_currentPos = getIntent().getIntExtra("position", 0);// paste this in onCreate()
Add this code in onResponse of Single Class -
try {
JSONArray jsonArray = response.getJSONArray("results");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
SingleInfo s = new SingleInfo();
s.set_rating(jsonObject.getString("rating"));
single.add(s);
}
//changed by Shoeb
SingleInfo _singleInfo = single.get(_currentPos); //position from previous activity
textView.setText(_singleInfo.get_rating());
//end changes
} catch (JSONException e) {
e.printStackTrace();
}
Add an extra to your intent
i.putExtra("position",position);
And on the other activity:
getIntent().getIntExtra("position", 0);