I have made an ListView with items, qty, rate and retrieved the data from MySQL but I need to add even my "Service Charges" and "Net Amount" to the ListView but I have "Service Charges" and "Net Amount" in the variable not in the MYSQL how can I insert this two into the ListView.
Here is my code:
public void getPostedJobsLocal(){
String url=Config.GET_PAYMENT_BILL;
String url1= local_job_id;
String URL=url+url1;
StringRequest stringRequest = new StringRequest(URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
showJSONPosted(response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(stringRequest);
}
private void showJSONPosted(String response) {
ParseJSONPayBillLocal pj = new ParseJSONPayBillLocal(response);
pj.parseJSONPayBillLocal();
CustomListPayBillLocal cl = new CustomListPayBillLocal(this, ParseJSONPayBillLocal.items, ParseJSONPayBillLocal.qty,ParseJSONPayBillLocal.rate);
lview.setAdapter(cl);
}
So how can insert the "Service Charges" and "Net Amount" which I have as variable into the ListView?
Its more of a hack. You can add the items to the String arrays before giving it to the Adapter.
Something like this,
private void showJSONPosted(String response) {
ParseJSONPayBillLocal pj = new ParseJSONPayBillLocal(response);
pj.parseJSONPayBillLocal();
ParseJSONPayBillLocal.items = append(ParseJSONPayBillLocal.items, "Service Charges");
ParseJSONPayBillLocal.qty = append(ParseJSONPayBillLocal.qty, "your_qty");
ParseJSONPayBillLocal.rate = append(ParseJSONPayBillLocal.rate, "your_rate");
ParseJSONPayBillLocal.items = append(ParseJSONPayBillLocal.items, "Net Amount");
ParseJSONPayBillLocal.qty = append(ParseJSONPayBillLocal.qty, "your_qty");
ParseJSONPayBillLocal.rate = append(ParseJSONPayBillLocal.rate, "your_rate");
CustomListPayBillLocal cl = new CustomListPayBillLocal(this, ParseJSONPayBillLocal.items, ParseJSONPayBillLocal.qty, ParseJSONPayBillLocal.rate);
lview.setAdapter(cl);
}
public static <T> T[] append(T[] arr, T element) {
final int N = arr.length;
arr = Arrays.copyOf(arr, N + 1);
arr[N] = element;
return arr;
}
Make a model class containing Service Charges and Net Amount
public class MyModel {
String serviceCharges;
String netAmount;
public MyModel (String serviceCharges, String netAmount){
this.serviceCharges= serviceCharges;
this.netAmount= netAmount;
}
public String getServiceCharges() {
return serviceCharges;
}
public void setServiceCharges(String serviceCharges) {
this.serviceCharges= serviceCharges;
}
public String getNetAmount() {
return netAmount;
}
public void setNetAmount(String netAmount) {
this.netAmount= netAmount;
}
}
Now you can create an ArrayList of MyModel class and add your services charges and net amount values:
ArrayList<MyModel> myModelArray = new ArrayList<MyModel>();
myModelArray.add(new MyModel("serviceCharge1","netAmount1"));
myModelArray.add(new MyModel("serviceCharge2","netAmount2"));
.......
.......
Now you can pass this myModelArray to your list adapter for binding data with the list view.
Retrieve values by:
myModelArray.get(position).getServiceCharges();
myModelArray.get(position). getNetAmount();
Note: Shift to retrofit, it is 4 times faster than volley.
Related
I want to execute taking data from JSON as shown below. But when
Toast.makeText(this, MangIDtrailer.size () + "..... check size of Array IDtrailer .....", Toast.LENGTH_LONG).show();
it returns 0.
I don't know what the cause is.
public class Main2Activity extends AppCompatActivity {
ListView Listmovie;
ArrayList<String> MangIDtrailer;
public static ArrayList<InfoMovie> inforMovieArrayList;
AdapterMovie adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
BottomNavigationView navView = findViewById(R.id.nav_view);
navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener);
String url1 ="http://the....ying";
inforMovieArrayList = new ArrayList<>();
MangIDtrailer = new ArrayList<>();
MangIDtrailer = GetIDMovie(url1);
inforMovieArrayList = DataMovie(MangIDtrailer);
Listmovie = (ListView) findViewById(R.id.ListMovie);
adapter = new AdapterMovie(this, R.layout.movielist, inforMovieArrayList);
Listmovie.setAdapter(adapter);
Listmovie.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(Main2Activity.this,Review_Movie.class);
intent.putExtra("IDmovie",i);
//Toast.makeText(MainActivity.this, ""+i, Toast.LENGTH_SHORT).show();
startActivity(intent);
}
});
}
public ArrayList<String> GetIDMovie (String Url) {
final ArrayList<String> ArrayID = new ArrayList<>();
final RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, Url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String IDTrailer;
JSONArray jsonArrayFreeMovies = response.getJSONArray("FreeMovies");
for (int i=0; i < jsonArrayFreeMovies.length(); i++) {
JSONObject jsonObjectFreeMovies = jsonArrayFreeMovies.getJSONObject(i);
IDTrailer = jsonObjectFreeMovies.getString("trailer_id");
ArrayID.add(IDTrailer);
Toast.makeText(Main2Activity.this, i+"************", Toast.LENGTH_SHORT).show();
}
Toast.makeText(Main2Activity.this, MangIDtrailer.get(2)+"check Data ", Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
});
queue.add(jsonObjectRequest);
queue.cancelAll(jsonObjectRequest);
return ArrayID;
}
public ArrayList <InfoMovie> DataMovie (ArrayList<String> MangIDtrailer) {
final ArrayList<InfoMovie> inforMovieArray = new ArrayList<>();
final String linkDetail = "http://tk/api/trailers/movDetail?trailer_id=";
final RequestQueue queue2 = Volley.newRequestQueue(this);
//////////////Check that MangIDtrailer.size () has no data////////////////////////////////////
Toast.makeText(this, MangIDtrailer.size()+".....check size of Array IDtrailer .....",Toast.LENGTH_LONG).show();
for (int i=0; i<MangIDtrailer.size(); i++) {
JsonObjectRequest jsonObjectRequest2 = new JsonObjectRequest(Request.Method.GET, linkDetail + MangIDtrailer.get(i) + "&test_fullVer=1", null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
String linkposter, linkbackdrop, namemovie, overviewmovie, Release_date, Urltrailer;
Float Vote_average;
String linkHot = "https://image.tmdb.org/t/p/w500/";
JSONObject jsonObjectInfo = null, jsonObjectMore = null;
JSONObject jsonopFreeMovies1 = response.getJSONObject("FreeMovies");
if (jsonopFreeMovies1.has("FreeMovies")) {
//Toast.makeText(MainActivity.this, "Cos ", Toast.LENGTH_SHORT).show();
JSONObject jsonObjectFreeMovies2 = jsonopFreeMovies1.getJSONObject("FreeMovies");
jsonObjectInfo = jsonObjectFreeMovies2.getJSONObject("Info");
jsonObjectMore = jsonObjectFreeMovies2.getJSONObject("More");
} else {
//Toast.makeText(MainActivity.this, "Khoong cos", Toast.LENGTH_SHORT).show();
jsonObjectInfo = jsonopFreeMovies1.getJSONObject("Info");
jsonObjectMore = jsonopFreeMovies1.getJSONObject("More");
}
namemovie = jsonObjectInfo.getString("title");
Urltrailer = jsonObjectInfo.getString("trailer_urls");
linkposter = linkHot + jsonObjectInfo.getString("thumbnail");
overviewmovie = jsonObjectMore.getString("overview");
linkbackdrop = linkHot + jsonObjectMore.getString("backdrop_path");
Release_date = jsonObjectMore.getString("release_date");
Vote_average = Float.valueOf(jsonObjectMore.getLong("vote_average"));
inforMovieArray.add(new InfoMovie(namemovie, overviewmovie, linkposter, linkbackdrop, Vote_average, Release_date));
Toast.makeText(Main2Activity.this,namemovie + "-" + overviewmovie + "-" + Vote_average, Toast.LENGTH_SHORT).show();
} catch (JSONException e) {
Toast.makeText(Main2Activity.this, "Lỗi", Toast.LENGTH_SHORT).show();
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(Main2Activity.this, "Lỗi Try catch", Toast.LENGTH_SHORT).show();
}
});
queue2.add(jsonObjectRequest2);
}
return inforMovieArray;
}
}
As you suggested
Toast.makeText(this, MangIDtrailer.size()+".....check size of Array IDtrailer .....",Toast.LENGTH_LONG).show();
This is where you are getting size zero, which is absolutely true, because you have only initialized your array MangIDtrailer and it is an empty array. Your function GetIDMovie(url1); has a loop which populates your MangIDtrailer array which is below where you have called the toast. So your array is empty and thus its size returns zero.
One handy tip for you, you should name your functions in camelCase with first letter of your word in lowercase. GetIDMovie(url1) seems more like a class constructor. :)
EDIT:
The above solves your initial problem.
To fully solve your problem, you have to understand that Network Operations are asynchronous, meaning they will execute after sometime or they may return no value at all depending on various conditions, like network bandwidth, your server state, the parameters passed to your HTTP requests, etc.
You have two network calls in your above code; in functions: GetIDMovie() and DataMovie(). The second function requires an array of IDs which is only available if your first request is complete and returns an array of ids. So what you would want to do is, only after you get the array of ids ie. in onResponse of GetIDMovie() after the for loop, you should make a call to DataMovie().
This however is really ugly solution. I hope you will research further for better solution.
I use the Volley Library in my app.
I use a method to transfer myself from Activity A to Activity B by intent.
StringURL StringURL
-------------- intent --------------
| Activity A | >---->> | Activity B |
-------------- --------------
mystring url ====> http://www.articler.ir/android_php/search.php?Method=rate&CAT=مهندسی%20عمران
Then in Activity B, I use the server to receive content from the server, but apparently, this content is received on Android less than 5 empty.
Please guide me exactly where it can be. I once again put this question in this link List View does not show anything bellow lollipop version and find root problem, But I do not understand why the Response from the server in Android 4.4 is empty. But the same Response is true on Android 5+. How to fix the problem? Please HELP me, thank you Again.
Android 5-
Android 5+
in Activity B :
public class FragmentOne extends Fragment {
private List<Model> myList = new ArrayList<Model>();
private ArrayList<String> authors;
private ArrayList<String> keywords;
String FirstURL ;
String SearchURL;
//my stirng url ===>
// http://www.articler.ir/android_php/search.php?Method=rate&CAT=مهندسی%20عمران
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_one, container, false);
final SwipeRefreshLayout swipeRefreshLayout = rootView.findViewById(R.id.fm_one);
final CustomListAdapter adapter = new CustomListAdapter(getActivity(), myList);
final ListView listView1 = (ListView) rootView.findViewById(R.id.myList1);
Intent intent = getActivity().getIntent();
FirstURL = intent.getStringExtra("SearchURL");
SearchURL = FirstURL.replaceAll(" ", "%20");
Log.d("Search", "Search: " + SearchURL);
myList.removeAll(myList);
swipeRefreshLayout.setRefreshing(true);
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(SearchURL, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d("VolleyRes", "response: " + response);
for (int i = 0; i < response.length(); i++) {
try {
JSONObject jsonObject = response.getJSONObject(i);
Model model = new Model();
model.setTitle(jsonObject.getString("title"));
model.setMainText(jsonObject.getString("mainText"));
model.setrate(jsonObject.getDouble("rate"));
model.setYear(jsonObject.getInt("year"));
model.setConfName(jsonObject.getString("confName"));
model.setProductId(jsonObject.getInt("productId"));
model.setCountView(jsonObject.getInt("countView"));
model.setPdfURL(jsonObject.getString("pdfURL"));
// authors is json array
authors = new ArrayList<String>();
JSONArray authorArray = jsonObject.getJSONArray("authors");
for (int j = 0; j < authorArray.length(); j++) {
if (!authors.contains(authorArray.getString(j)) && !authorArray.isNull(j)) {
authors.add((String) authorArray.get(j));
}
}
model.setAuthor(authors);
// Keywords is json array
keywords = new ArrayList<String>();
JSONArray keywordArray = jsonObject.getJSONArray("Keywords");
for (int k = 0; k < keywordArray.length(); k++) {
if (!keywords.contains(keywordArray.getString(k)) && !keywordArray.isNull(k)) {
keywords.add((String) keywordArray.get(k));
}
}
model.setKeywords(keywords);
myList.add(model);
} catch (JSONException e) {
e.printStackTrace();
}
}
listView1.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("VolleyErr", "ErrorMassage: " + error.getMessage());
}
});
AppController.getInstance().addToRequestQueue(jsonArrayRequest);
swipeRefreshLayout.setRefreshing(false);
listView1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
swipeRefreshLayout.setRefreshing(true);
int year = myList.get(position).getYear();
int productId = myList.get(position).getProductId();
int countView = myList.get(position).getCountView();
double rate = myList.get(position).getrate();
String title = myList.get(position).getTitle();
String mainText = myList.get(position).getMainText();
String confName = myList.get(position).getConfName();
ArrayList authors = myList.get(position).getAuthor();
ArrayList keywords = myList.get(position).getKeywords();
String pdfURL = myList.get(position).getPdfURL();
SharedPreferences prefs = PreferenceManager.
getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = prefs.edit();
editor.putInt("productId", productId); //InputString: from the EditText
editor.putInt("countView", countView);
editor.putFloat("rate", (float) rate);
editor.putString("pdfURL",pdfURL);
editor.putString("title",title);
editor.putString("mainText",mainText);
editor.putString("confName",confName);
editor.putString("authors", String.valueOf(authors));
editor.putString("keywords", String.valueOf(keywords));
editor.putInt("year", year);
editor.commit();
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
swipeRefreshLayout.setRefreshing(false);
Intent intent = new Intent(getContext(),DetailActivity.class);
startActivity(intent);
// finish();
}
}, 1500);
}
});
swipeRefreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener(){
#Override
public void onRefresh() {
((MyTabActivity)getActivity()).refreshNow();
Toast.makeText(getContext(), "بروزرسانی صفحه!", Toast.LENGTH_SHORT).show();
}
});
return rootView;
}
}
My AppController:
public class AppController extends Application {
public static final String TAG = AppController.class.getSimpleName();
private RequestQueue mRequestQueue;
private static AppController mInstance;
#Override
public void onCreate() {
super.onCreate();
mInstance = this;
}
public static synchronized AppController getInstance() {
return mInstance;
}
public RequestQueue getRequestQueue() {
if (mRequestQueue == null) {
mRequestQueue = Volley.newRequestQueue(getApplicationContext());
}
return mRequestQueue;
}
public <T> void addToRequestQueue(Request<T> req, String tag) {
req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
getRequestQueue().add(req);
}
public <T> void addToRequestQueue(Request<T> req) {
req.setTag(TAG);
getRequestQueue().add(req);
}
public void cancelPendingRequests(Object tag) {
if (mRequestQueue != null) {
mRequestQueue.cancelAll(tag);
}
}
}
I realized that URL with Persian fonts on Android less than 5 is not supported. So I need to change the string by encoding it so I used the method below to change it.
//this is initial string url ====> http://www.articler.ir/android_php/search.php?Method=rate&CAT=مهندسی%20عمران
String MyKey = مهندسی عمران;
final String EncodeKey= URLEncoder.encode(MyKey , "UTF-8");
String EncodeURL = " http://www.articler.ir/android_php/search.php?Method=rate&CAT= " + EncodeKey;
after changing this part, my response is correct, like 5+ version;
I want to get string from arraylist inside oncreateview fragment but i cant figure itout since no position index has been pass. get(position) return error.
String price = arrayList.get(position).getPrice();
i need to get string price and settext for price.this is my main concern.
this values should return from arraylist.
this is response JSON array from volley using mysingleton.
Single Product Response: [{"price":"75","date":"2017-07-13 03:25:31","pk_i_id":"4"}]
this main activty fragment
public class MainActivityFragment extends Fragment {
private TextView product,price,date,title;
private String product_id;
ArrayList<ProductItem> arrayList = new ArrayList<>();
Context context;
public MainActivityFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_main_activity, container, false);
product = (TextView) view.findViewById(R.id.tv1);
title = (TextView) view.findViewById(R.id.tvTitle);
price = (TextView) view.findViewById(R.id.tvPrice);
date = (TextView) view.findViewById(R.id.tvDate);
if (getArguments() != null) {
Log.i(TAG, "getArgument is not null");
product_id = getArguments().getString("product_id");
ProductBackgroundTask productBackgroundTask = new ProductBackgroundTask(this.getActivity(), product_id);
arrayList = productBackgroundTask.getList();
String price = arrayList.get(position).getPrice();
// Log.d(TAG, "price: " + price);
product.setText(product_id);
// price.setText(price);
}else {
Log.i(TAG, "getArgument is null");
}
return view;
}
}
this is task to get arraylist using volley
public class ProductBackgroundTask {
private Context context;
ArrayList<ProductItem> arrayList = new ArrayList<>();
String json_url = "phpfile.php";
private String product_id;
public ProductBackgroundTask(Context context, String product_id) {
this.context = context;
this.product_id = product_id;
}
public ArrayList<ProductItem> getList(){
StringRequest stringRequest = new StringRequest(Request.Method.POST, json_url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Single Product Response: " + response);
try {
JSONArray jsonarr = new JSONArray(response);
for (int i = 0; i < jsonarr.length(); i++) {
JSONObject jsonobj = jsonarr.getJSONObject(i);
ProductItem productItem = new ProductItem(jsonobj.getString("price"), jsonobj.getString("date"), jsonobj.getInt("pk_i_id"));
arrayList.add(productItem);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("product_id", product_id);
return params;
}
};
MySingleton.getInstance(context).addToRequestQueue(stringRequest);
return arrayList;
}
}
and this is class of array list
public class ProductItem {
private String Price,Date;
private int ProductId;
public ProductItem(String Price, String Date, int ProductId){
this.setPrice(Price);
this.setDate(Date);
this.setProductId(ProductId);
}
public int getProductId() {
return ProductId;
}
public void setProductId(int productId) {
ProductId = productId;
}
public String getPrice() {
return Price;
}
public void setPrice(String price) {
Price = price;
}
public String getDate() {
return Date;
}
public void setDate(String date) {
Date = date;
}
Clearly in your oncreate you haven’t initialized the product item and you cannot parse the complete list.You can try two to solve this
1.Pass specific item number instead of position i.e
say if you want to show 4th item then position=3
2.Or write a loop like this to parse entire arrayList like this
for(ProductItem productItem:arrayList){
String price = productItem.getPrice();
// Log.d(TAG, "price: " + price);
product.setText(product_id);
price.setText(price);
}
Mistake you're doing is that in the MainActivityFragment your trying to assign the value to the arrayList even before the data is added to the arrayList in the ProductBackgroundTask-getList. That's the reason you are getting the list null all the time. Try to use interfaces.
1.Make your MainActivityFragment implement the interface.
2.Set the value to the interface method once you get the data from the server.
3.Get the data in the MainActivityFragment inside interface method and do all the operation you're doing inside the onCreateView method.
Now your arraylist will have the data whatever you received from the server.
Below is the link for the example on interfaces if you haven't used them before. He is doing exactly as your requirement.
https://www.justinmccandless.com/post/setting-up-a-callback-function-in-android/
Allow me. The arrayList that you return from getList isn't populated at the time you call String price = arrayList.get(position).getPrice();. The server call using volley takes some time to process and that's when the onResponse gets called. This happens AFTER you've returned the arrayList which is in fact empty.
The sequence of events is as follows.
• Call to arrayList = productBackgroundTask.getList(); which returns an empty ArrayList.
• String price = arrayList.get(position).getPrice();
Now after a while..
• onResponse inside getList() gets called.
Do you now see why it's empty?
Simple Solution: • Define a simple interface ProductListener alongside ProductBackgroundTask. (With only a single abstract method onProducts).
• Instantiate it inside the Fragment's onCreateView using an anonymous class and pass it to the constructor of ProductListener to save it for later use. Do whatever you want to do with the products inside the onProducts method. (Since that will be called with the actual data)
• Call its onProducts method with the data that's parsed and fetched inside the onResponse method.
ProductBackgroundTask code:
public class ProductBackgroundTask {
private Context context;
// I removed the instance ArrayList since that can be made
// local.
// Here, we add a reference to our callback interface as we can use it later.
private ProductListener listener;
String json_url = "http://192.168.43.55/android/v1/productList.php";
private String product_id;
// Instantiate this class using an additional listener argument
// which would be a concrete implementation of our interface.
public ProductBackgroundTask(Context context, String product_id, ProductListener listener) {
this.context = context;
this.product_id = product_id;
this.listener = listener;
}
// getList should not return anything,
// so I keep the return as void.
public void getList() {
StringRequest stringRequest = new StringRequest(Request.Method.POST, json_url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
ArrayList<ProductItem> arrayList = new ArrayList<>();
Log.d(TAG, "Single Product Response: " + response);
try {
JSONArray jsonarr = new JSONArray(response);
for (int i = 0; i < jsonarr.length(); i++) {
JSONObject jsonobj = jsonarr.getJSONObject(i);
ProductItem productItem = new ProductItem(jsonobj.getString("price"), jsonobj.getString("date"), jsonobj.getInt("pk_i_id"));
arrayList.add(productItem);
}
// Notice this line here, this is what
// calls the callback with the products.
listener.onProducts(arrayList);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("product_id", product_id);
return params;
}
};
MySingleton.getInstance(context).addToRequestQueue(stringRequest);
}
}
// Callback interface, we would need a concrete implementation
// of this and pass that to the constructor of ProductBackgroundTask.
interface ProductListener {
void onProducts(ArrayList<ProductItem> products);
}
The code inside onCreateView:
ProductBackgroundTask productBackgroundTask = new ProductBackgroundTask(this.getActivity(), product_id, new ProductListener() {
// This method will be called with the needed products.
// Give an anonymous class implementation of our interface
// right here since we won't be using it anymore.
public void onProducts(ArrayList<ProductItem> products) {
// Get the price you want.
String str = arrayList.get(0).getPrice();
// Use str wherever necessary. Use the UI thread here if you need
// to change any visible elements on the screen.
}
});
// Simply call this method to get the ball rolling.
productBackgroundTask.getList();
This is a concrete implementation of the this answer and you won't be changing much code.
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.
Please help me out to load more data from the server upon scrolling my RecyclerView . Here I have successfully created RecyclerView by loading data from my Mysql server by using volley string request.
Here is my code.
private void populateRecycleView() {
if (Utility.checkNetworkConnection(this)) {
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setTitle("Searching...");
progressDialog.setMessage("Searching for the blood donor. Please wait a moment.");
progressDialog.setCancelable(false);
progressDialog.show();
StringRequest stringRequest = new StringRequest(Request.Method.POST, Constants.GET_DONORS_URL,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
progressDialog.dismiss();
try {
JSONArray jsonArray = new JSONArray(response);
int count = 0;
while (count < jsonArray.length()) {
JSONObject jsonObject = jsonArray.getJSONObject(count);
String firstName = jsonObject.getString("fName");
String secondName = jsonObject.getString("sName");
String email = jsonObject.getString("emailid");
String password = jsonObject.getString("pass");
String mobile = jsonObject.getString("mobile");
String bloodRt = jsonObject.getString("blood");
String age = jsonObject.getString("age");
String gender = jsonObject.getString("gender");
String country = jsonObject.getString("country");
String location = jsonObject.getString("location");
String latitude = jsonObject.getString("latitude");
String longitude = jsonObject.getString("longitude");
String profilePicFIleName = jsonObject.getString("picname");
String profilePicURL = jsonObject.getString("pic");
Donor donor = new Donor(firstName, secondName, email, password, mobile, bloodRt, age, gender,
country, location, latitude, longitude, profilePicFIleName, profilePicURL);
donorsList.add(donor);
count++;
}
donorsAdapter = new DonorsAdapter(FindDonorResult.this, donorsList);
recyclerView = (RecyclerView) findViewById(R.id.rv_search_result_donor);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(FindDonorResult.this));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(donorsAdapter);
donorsAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
progressDialog.dismiss();
Toast.makeText(FindDonorResult.this, "Active data network is not available.", Toast.LENGTH_LONG).show();
}
}
) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("bloodGroup", bloodGroup);
return params;
}
};
NetworkRequestSingleTon.getOurInstance(this).addToRequestQue(stringRequest);
} else {
Utility.checkNetworkConnectionFound(this);
}
}
And this is my RecyclerView adapter...
public class DonorsAdapter extends RecyclerView.Adapter<DonorsAdapter.CustomViewHolder> {
private Context context;
private ArrayList<Donor> donorList;
private String bloodGroup;
public DonorsAdapter(Context context, ArrayList<Donor> donorList) {
this.context = context;
this.donorList = donorList;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_blood_donors_result,
parent, false);
return new CustomViewHolder(view);
}
#Override
public void onBindViewHolder(CustomViewHolder holder, int position) {
final Donor donor = donorList.get(position);
String displayName = donor.getFirstName() + " " + donor.getSecondName();
holder.tvDisplayName.setText(displayName);
holder.tvEmailID.setText(donor.getEmail());
String userProfileURL = donor.getProfilePicURL();
if (!userProfileURL.equals("")) {
Picasso.with(context).load(userProfileURL).resize(80, 80).centerCrop().
into(holder.ivProfilePic);
} else {
holder.ivProfilePic.setImageResource(R.drawable.ic_person_white_24dp);
}
bloodGroup = donor.getBloodGroup();
if (bloodGroup.equals("A+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.a_);
else if (bloodGroup.equals("A-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.a_negative);
else if (bloodGroup.equals("B+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.b_positive);
else if (bloodGroup.equals("B-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.b_negative);
else if (bloodGroup.equals("O+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.o_positive);
else if (bloodGroup.equals("O-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.o_negative);
else if (bloodGroup.equals("AB+"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.ab_positive);
else if (bloodGroup.equals("AB-"))
holder.ivBloodTypeDisplay.setImageResource(R.drawable.ab_negative);
if(Utility.isNetworkEnabled){
holder.constraintLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, DisplayDonorDetails.class);
intent.putExtra("donor", donor);
context.startActivity(intent);
}
});
}else {
Toast.makeText(context, "Network not available.", Toast.LENGTH_SHORT).show();
}
}
#Override
public int getItemCount() {
if(donorList != null){
return donorList.size();
}else {
return 0;
}
}
public class CustomViewHolder extends RecyclerView.ViewHolder {
ImageView ivProfilePic, ivBloodTypeDisplay, ivArrow;
TextView tvDisplayName;
TextView tvEmailID;
ConstraintLayout constraintLayout;
public CustomViewHolder(View itemView) {
super(itemView);
ivProfilePic = (ImageView) itemView.findViewById(R.id.civ_user_profile_picture);
ivBloodTypeDisplay = (ImageView) itemView.findViewById(R.id.civ_user_blood_type_display);
ivArrow = (ImageView) itemView.findViewById(R.id.civ_arrow);
tvDisplayName = (TextView) itemView.findViewById(R.id.tvUserNameOnRV);
tvEmailID = (TextView) itemView.findViewById(R.id.tvEmailDisplayOnRV);
constraintLayout = (ConstraintLayout) itemView.findViewById(R.id.recycle_view_item_container);
}
}
}
Populate your donorsAdapter only with the 50 first elements of your donorsList, create a function that save the position of the latest element displayed and add other 50 donors to your adapter starting from the latest position saved when you need it.
Hope it helps.
EDIT
First create an emptyList:
List<Donor> subElements = new ArrayList<>();
and pass it to your adapter:
donorsAdapter = new DonorsAdapter(FindDonorResult.this, subElements);
Now you can create a method like this (you can call in onClick event for example):
private int LAST_POSITION = 0;
private int DONORS_NUM_TOSHOW = 50;
public void showMoreDonors(){
if(donarsList.size() > Last_postion+50){
List<Donor> tempList = new ArrayList<Donor>(donorsList.subList(Last_postion,Last_postion+DONORS_NUM_TOSHOW));
for(Donor a : tempList){
subElements.add(a);
}
Last_postion += DONORS_NUM_TOSHOW;
donorsAdapter.notifyDataSetChanged();
}else{
List<Donor> tempList = new ArrayList<Donor>(donorsList.subList(Last_postion,donorsList.size()));
for(Donor a : tempList){
subElements.add(a);
}
donorsAdapter.notifyDataSetChanged();
}
}
Remember to check when donorsList is over.
I didn't test it, but i hope it is usefull to understand the idea.
Finally, I sort this out. I have got an awesome tutorial from this blog.
http://android-pratap.blogspot.in/2015/06/endless-recyclerview-with-progress-bar.html.
I made some changes to populate the list because my data is on a remote server and by using volley library I fetched the data into the list. Remaining things are same.