This question already has answers here:
Reversing an Array in Java [duplicate]
(15 answers)
Closed 4 years ago.
I have source code of an app which displays the list of values as uploaded in the backend server, but the problem is it displays values in opposite order (Things uploaded older is listed first) I want it to be sorted just opposite (By Date).
public class SelectQuizActivity extends AppCompatActivity {
private static final String TAG = SelectQuizActivity.class.getSimpleName();
private int categoryId;
private String catName;
private String catImage;
private ImageView categoryImage;
private TextView categoryName;
private RecyclerView quizRecyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_select_quiz);
categoryId = getIntent().getExtras().getInt(Constants.CATEGORY);
catName = getIntent().getExtras().getString(Constants.CATEGORY_NAME);
catImage = getIntent().getExtras().getString(Constants.CATEGORY_IMAGE);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
if(getSupportActionBar() != null){
getSupportActionBar().setElevation(0);
}
setTitle("");
categoryImage = (ImageView)findViewById(R.id.quiz_category_image);
categoryName = (TextView)findViewById(R.id.quiz_category_name);
quizRecyclerView = (RecyclerView)findViewById(R.id.quiz_category);
quizRecyclerView.setLayoutManager(new GridLayoutManager(SelectQuizActivity.this, 3));
quizRecyclerView.setHasFixedSize(true);
if(Helper.isNetworkAvailable(this)){
allSubcategoryInCategory(catName);
}else{
DisplayMessage.displayErrorMessage(this, "No network available");
}
}
private void allSubcategoryInCategory(String name){
Map params = getParams(name);
GsonRequest<SingleQuizObject[]> serverRequest = new GsonRequest<SingleQuizObject[]>(
Request.Method.POST,
Constants.PATH_TO_QUIZ_SUBCATEGORIES,
SingleQuizObject[].class,
params,
createRequestSuccessListener(),
createRequestErrorListener());
((CustomApplication)getApplication()).getNetworkCall().callToRemoteServer(serverRequest);
}
private Map getParams(String name){
Map<String, String> params = new HashMap<String,String>();
params.put(Constants.NAME, name);
return params;
}
private Response.Listener<SingleQuizObject[]> createRequestSuccessListener() {
return new Response.Listener<SingleQuizObject[]>() {
#Override
public void onResponse(SingleQuizObject[] response) {
try {
if(response != null){
categoryName.setText(catName + " subcategories");
String serverImagePath = Constants.PUBLIC_FOLDER + catImage;
RequestOptions requestOptions = new RequestOptions();
requestOptions.diskCacheStrategy(DiskCacheStrategy.ALL);
Glide.with(SelectQuizActivity.this).load(serverImagePath).apply(requestOptions.fitCenter().override(80, 80)).into(categoryImage);
ArrayList<SingleQuizObject> list = arrayToListObject(response);
Collections.reverse(list);
CategoryAdapter mAdapter = new CategoryAdapter(SelectQuizActivity.this, arrayToListObject(list));
quizRecyclerView.setAdapter(mAdapter);
} else{
displayErrorMessage(SelectQuizActivity.this, "No subcategory found ");
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
}
private Response.ErrorListener createRequestErrorListener() {
return new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
};
}
private List<SingleQuizObject> arrayToListObject(SingleQuizObject[] response){
List<SingleQuizObject> allCategories = new ArrayList<>();
Collections.addAll(allCategories, response);
return allCategories;
}
}
Above code take input from category adapter and displays it as recycler view
Reverse list by Java Collection class
Collections.reverse(arrayToListObject(response));
or reverse RecyclerView items.
LinearLayoutManager lm = new LinearLayoutManager(YourActivity.this);
lm.setReverseLayout(true);
lm.setStackFromEnd(true);
Edit Example
As you are not doing right thing, here is the way
ArrayList<SingleQuizObject> list = arrayToListObject(response);
Collections.reverse(list);
CategoryAdapter mAdapter = new CategoryAdapter(SelectQuizActivity.this, list);
Reason
You reversed another copy of list, and you inserted another list. So first hold list, reverse it, and insert same list in adapter.
First call this
Collections.reverse(arrayToListObject(response));
then
CategoryAdapter mAdapter = new CategoryAdapter(SelectQuizActivity.this, arrayToListObject(response));
quizRecyclerView.setAdapter(mAdapter);
java.util.Collections.reverse(arrayToListObject(response))
Related
I 've problem with display data in ListView. I get data from Retrofit response, but my activity, which should display this data, is just beeing blank, all the time. I am sure, that I've receiving data, I've checked it, in console.
Model class
public class itemList_model {
#SerializedName("results")
private List<itemList_Results> results;
public List<itemList_Results> getResults() {
return results;
}
public static class itemList_Results{
#SerializedName("title")
String title;
#SerializedName("vote_average")
Double vote;
#SerializedName("genre_ids")
List<Integer> genresId;
#SerializedName("release_date")
String releaseDate;
public itemList_Results(String title, Double vote, String releaseDate) {
this.title = title;
this.vote = vote;
this.releaseDate = releaseDate;
}
public String getTitle() {
return title;
}
public Double getVote() {
return vote;
}
public List<Integer> getGenresId() {
return genresId;
}
public String getReleaseDate() {
return releaseDate;
}
}
public class itemList_genresId{
#SerializedName("genre_ids")
int id;
public int getId() {
return id;
}
}
}
adapter class
public class genres_adapter extends ArrayAdapter<itemList_model.itemList_Results> {
RetrofitCalls calls;
public genres_adapter(#NonNull Context context, ArrayList<itemList_model.itemList_Results> list) {
super(context, 0, list);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View itemView = convertView;
if (itemView == null){
itemView = LayoutInflater.from(getContext()).inflate(R.layout.genres_item_view, parent, false);
}
itemList_model.itemList_Results model = getItem(position);
TextView title = itemView.findViewById(R.id.title);
title.setText(model.getTitle());
TextView vote = itemView.findViewById(R.id.vote);
vote.setText(String.valueOf(model.getVote()));
TextView release = itemView.findViewById(R.id.release);
release.setText(model.getReleaseDate());
return itemView;
}
}
activity java class
ArrayList<itemList_model.itemList_Results> arrayList;
genres_adapter adapter;
String title = "";
Double average_votes = 0.0;
String date = "";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_genres_list_view);
arrayList = new ArrayList<itemList_model.itemList_Results>();
adapter = new genres_adapter(this, arrayList);
ListView listView = (ListView) findViewById(R.id.genres_listView);
listView.setAdapter(adapter);
getListViewItems();
}
public void getListViewItems(){
String url = "https://api.themoviedb.org/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiCall api = retrofit.create(apiCall.class);
Call<itemList_model> call = api.getHorror();
call.enqueue(new Callback<itemList_model>() {
#Override
public void onResponse(Call<itemList_model> call, Response<itemList_model> response) {
if (!response.isSuccessful()) {
Log.i(TAG, "onResponse: " + response.code());
}
List<itemList_model.itemList_Results> list = response.body().getResults();
for (itemList_model.itemList_Results model : list){
title =model.getTitle();
average_votes = Double.valueOf(model.getVote());
date =model.getReleaseDate();
}
list.add(new itemList_model.itemList_Results(title,average_votes,date));
}
#Override
public void onFailure(Call<itemList_model> call, Throwable t) {
Log.i(TAG, "onFailure: "+t.getMessage());
}
});
}
activity, that contains ListView, is called activity_genres_list_view
activity which will be used by adapter, is called genres_item_view
I'm guess, it's about data from list, maybe it's not being added?
Apparently, you should add your list to adapter after you received it:
adapter.addAll(list);
I cannot see any notifyDataSetChanged() call in your code. When the response is found from the Retrofit call, you need to update the list which was passed to the adapter and call notifyDataSetChanged on your adapter to see the effect.
Hence you might consider doing something like the following.
public void getListViewItems(){
String url = "https://api.themoviedb.org/";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create())
.build();
apiCall api = retrofit.create(apiCall.class);
Call<itemList_model> call = api.getHorror();
call.enqueue(new Callback<itemList_model>() {
#Override
public void onResponse(Call<itemList_model> call, Response<itemList_model> response) {
if (!response.isSuccessful()) {
Log.i(TAG, "onResponse: " + response.code());
}
// Do not create a new list here. Use the arrayList which was declared before and passed to the adapter
// List<itemList_model.itemList_Results> list = response.body().getResults();
// Clear the arrayList before pushing new data
arrayList.clear();
for (itemList_model.itemList_Results model : list){
title =model.getTitle();
average_votes = Double.valueOf(model.getVote());
date = model.getReleaseDate();
// Add the data into the arrayList instead of the list
arrayList.add(new itemList_model.itemList_Results(title,average_votes,date));
}
// Now call notifyDataSetChanged on your adapter to see the changes in the ListView
adapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<itemList_model> call, Throwable t) {
Log.i(TAG, "onFailure: "+t.getMessage());
}
});
}
Hope that fixes your problem.
Nothing appear because you are setting adapter before getting information :
adapter = new genres_adapter(this, arrayList);//array list is still empty here
listView.setAdapter(adapter);
getListViewItems();
what yo should do is setting adapter once you get the list ! or call notifydatasetChanged on your adapter after you get your informations !
{
.....
arrayList.add(new itemList_model.itemList_Results(title,average_votes,date));
.....
}
adapter.notifyDataSetChanged();
I am quite new to the Android Development and I really need your help. My problem is in the MainActivity below. The app essentially displays a list of movies in the main activity and the movie details in another activity. And the problem is that whenever a user comes back from the MovieActivity to the MainActivity, the loader starts loading data again, although the movies are already there. And then it can not stop loading the data. It is really annoying. I want to get rid of this. So when a user comes back to the MainActivity, the loader will know that there is already loaded data and will not load anything again.If it helps, here is my full GitHub repo https://github.com/mateuszwojnarowicz/PopularMovies
I am stuck for about 3 weeks and have tried hundreds of possible solutions. Nothing seems to work. I feel really desperate.
Thank you so much for help,
Matthew
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<String> {
private MovieAdapter mAdapter;
private ArrayList<Movie> mMoviesCollection;
private SharedPreferences sharedPreferences;
private Resources resources;
private LoaderManager loaderManager;
private Loader<String> loader;
private RecyclerView.LayoutManager layoutManager;
private String sortBy;
#BindView(R.id.pb)
ProgressBar progressBar;
#BindView(R.id.er)
TextView errorTextView;
#BindView(R.id.rv)
RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mMoviesCollection = new ArrayList<Movie>();
sharedPreferences = getSharedPreferences(Constants.SHARED_PREFS, Activity.MODE_PRIVATE);
resources = getResources();
sortBy = sharedPreferences.getString(Constants.KEY_SORT, null);
setSharedPref();
layoutManager = new GridLayoutManager(this, calculateNoOfColumns(this));
loaderManager = getLoaderManager();
loader = loaderManager.getLoader(Constants.LOADER_MOVIES_ID);
initialize();
makeOperationLoadMovies(sortBy);
}
public static int calculateNoOfColumns(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
int noOfColumns = (int) (dpWidth / 150);
return noOfColumns;
}
//Set first-launch pref and set title according to pref
private void setSharedPref(){
if(!sharedPreferences.contains(Constants.KEY_SORT)) {
saveData(Constants.VALUE_POP);
setTitle(resources.getString(R.string.title_pop));
} else {
if (Objects.equals(sharedPreferences.getString(Constants.KEY_SORT, null), Constants.VALUE_POP)) {
setTitle(resources.getString(R.string.title_pop));
}
if (Objects.equals(sharedPreferences.getString(Constants.KEY_SORT, null), Constants.VALUE_TOP)) {
setTitle(resources.getString(R.string.title_top));
}
}
}
//Set up the RecyclerView
private void initialize(){
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
mMoviesCollection = new ArrayList<>();
mAdapter = new MovieAdapter(mMoviesCollection, this, this);
recyclerView.setAdapter(mAdapter);
}
private void makeOperationLoadMovies(String SORT_BY){
Bundle bundle = new Bundle();
bundle.putString(Constants.LOADER_MOVIES_EXTRA, SORT_BY);
if(recyclerView.isDirty()){
}
else if(loader==null){
loaderManager.initLoader(Constants.LOADER_MOVIES_ID, bundle, this);
}else{
loaderManager.restartLoader(Constants.LOADER_MOVIES_ID, bundle, this);
}
}
//Update shared pref
private void saveData(String SORT_VALUE){
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(Constants.KEY_SORT, SORT_VALUE);
editor.apply();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id){
case R.id.menu_fav:
startActivity(new Intent(MainActivity.this, FavoritesActivity.class));
break;
case R.id.menu_pop:
saveData(Constants.VALUE_POP);
Toast.makeText(this, resources.getString(R.string.message_popularity),Toast.LENGTH_LONG).show();
break;
case R.id.menu_top:
saveData(Constants.VALUE_TOP);
Toast.makeText(this, resources.getString(R.string.message_rating),Toast.LENGTH_LONG).show();
break;
}
return super.onOptionsItemSelected(item);
}
#Override
protected void onPause() {
super.onPause();
Parcelable recyclerViewState;
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();//save
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
}
#Override
protected void onPostResume() {
super.onPostResume();
Parcelable recyclerViewState;
recyclerViewState = recyclerView.getLayoutManager().onSaveInstanceState();//save
recyclerView.getLayoutManager().onRestoreInstanceState(recyclerViewState);
}
#SuppressLint("StaticFieldLeak")
#Override
public Loader<String> onCreateLoader(int id, final Bundle args) {
return new AsyncTaskLoader<String>(this) {
#Override
protected void onStartLoading() {
super.onStartLoading();
forceLoad();
progressBar.setVisibility(View.VISIBLE);
errorTextView.setVisibility(View.INVISIBLE);
}
#Override
public void deliverResult(String data) {
super.deliverResult(data);
}
#Override
public String loadInBackground() {
String jsonString = "";
URL url = NetworkUtils.buildUrl(args.getString(Constants.LOADER_MOVIES_EXTRA));
try {
jsonString += NetworkUtils.getResponseFromHttpUrl(url);
} catch (IOException e) {
e.printStackTrace();
}
if(jsonString.isEmpty()){
} else {
try {
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray(Constants.JSON_KEY_MOVIE_RESULTS);
for (int i = 0; i < jsonArray.length(); i++) {
//Get 1 movie from JSON
String mTitle;
int mId;
String mPosterUrl;
String mPlot;
double mUserRating;
String mReleaseDate;
JSONObject Jmovie = (JSONObject) jsonArray.get(i);
mTitle = Jmovie.getString(Constants.JSON_KEY_MOVIE_TITLE);
mId = Jmovie.getInt(Constants.JSON_KEY_MOVIE_ID);
mPosterUrl = NetworkUtils.getPosterString(Jmovie.getString(Constants.JSON_KEY_MOVIE_POSTER_PATH));
mPlot = Jmovie.getString(Constants.JSON_KEY_MOVIE_OVERVIEW);
mUserRating = Jmovie.getDouble(Constants.JSON_KEY_MOVIE_VOTE_AVERAGE);
mReleaseDate = Jmovie.getString(Constants.JSON_KEY_MOVIE_RELEASE_DATE);
//Get videos
ArrayList<Video> mVideos = new ArrayList<Video>();
URL videosURL = NetworkUtils.buildUrlVideos(String.valueOf(mId));
String videosJSON = NetworkUtils.getResponseFromHttpUrl(videosURL);
JSONObject jsonObjectVideos = new JSONObject(videosJSON);
JSONArray jsonArrayVideos = jsonObjectVideos.getJSONArray(Constants.JSON_KEY_VIDEO_RESULTS);
if(jsonArrayVideos.length()==0){
mVideos = null;
} else {
for(int v = 0; v < jsonArrayVideos.length(); v++){
JSONObject Jvideo = (JSONObject) jsonArrayVideos.get(v);
String mVideoName;
String mVideoUrlString;
mVideoName = Jvideo.getString(Constants.JSON_KEY_VIDEO_NAME);
mVideoUrlString = "https://www.youtube.com/watch?v="+Jvideo.getString(Constants.JSON_KEY_VIDEO_KEY);
Video video = new Video(mVideoName, mVideoUrlString);
mVideos.add(video);
}
}
//GetReviews
ArrayList<Review> mReviews = new ArrayList<Review>();
URL reviewsURL = NetworkUtils.buildUrlReviews(String.valueOf(mId));
String reviewsJSON = NetworkUtils.getResponseFromHttpUrl(reviewsURL);
JSONObject jsonObjectReviews = new JSONObject(reviewsJSON);
JSONArray jsonArrayReviews = jsonObjectReviews.getJSONArray(Constants.JSON_KEY_REVIEW_RESULTS);
if(jsonArrayReviews.length()!=0) {
for(int r = 0; r < jsonArrayReviews.length(); r++){
JSONObject Jreview = (JSONObject) jsonArrayReviews.get(r);
String mReviewName;
String mReviewText;
mReviewName = Jreview.getString(Constants.JSON_KEY_REVIEW_AUTHOR);
mReviewText = Jreview.getString(Constants.JSON_KEY_REVIEW_CONTENT);
Review review = new Review(mReviewName, mReviewText);
mReviews.add(review);
}
}
Movie movie = new Movie(mTitle, mId, mPosterUrl, mPlot, mUserRating, mReleaseDate, mVideos, mReviews);
mMoviesCollection.add(movie);
}
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
}
return null;
}
};
}
#Override
public void onLoadFinished(Loader<String> loader, String data) {
progressBar.setVisibility(View.GONE);
mAdapter.notifyDataSetChanged();
}
#Override
public void onLoaderReset(Loader<String> loader) {
}
}
Because you are new to Android there is a lot wrong. So, many people probably won't want to chime in. Regardless, I'm new as well and in the same class as you are right now, so I'll give it a shot.
First, your loader is not returning the correct data type. Your loader should be of Loader<List<Movie>> and it should return a new AsyncTaskLoader<List<Movie>>. The reason you want this is to make use of everything the AsyncTaskLoader has to offer. I'll explain further.
Second, we'll cache the data inside the loader by moving the initial reference from the Activity into the loader.
So move private ArrayList<Movie> mMoviesCollection; as an instance variable of your AsyncTaskLoader. Remove the line mMoviesCollection = new ArrayList<Movie>(); from both your onCreate and initialize methods.
In your AsyncTaskLoader, you need to check if your data exists already in your onStartLoading before forceLoad and implement deliverResult.
So, your onStartLoading() should look like this:
#Override
protected void onStartLoading() {
super.onStartLoading();
if(mMoviesCollection.isEmpty()){
forceLoad();
progressBar.setVisibility(View.VISIBLE);
errorTextView.setVisibility(View.INVISIBLE);
} else {
deliverResult(mMoviesCollection)
}
}
And your deliverResult should look like this:
#Override
public void deliverResult(List<Movie> data) {
mMoviesCollection = data;
super.deliverResult(data);
}
Now you need to implement a setData(List<Movie> movies) method that sets your adapter's data instance variable and calls notifyDataSetChanged() in your Adapter. Like so:
public void setData(List<Movie> movies){
mMovies = movies;
notifyDataSetChanged();
}
Get rid of the List<Movie> from your adapter's constructor. This way you can construct the adapter without any data. The adapter's getItemCount() should return 0 if the data is null and the recyclerView will not try to build the view.
With that done you can then call onLoadFinished like this:
#Override
public void onLoadFinished(Loader<List<Movie>> loader, List<Movie> data) {
progressBar.setVisibility(View.GONE);
mAdapter.setData(data);
}
EDIT: Made a correction to account for the ArrayList instantiating as an Instance variable. You can either not instantiate the mMoviesCollection there and then do so later or just check if its empty with mMoviesCollection.isEmpty() as I changed above in onStartLoading.:
EDIT:
You need to get your libraries straight, you are using android.app in some places and android.support in others.
So in your imports change these:
import android.app.LoaderManager;
import android.content.AsyncTaskLoader;
import android.content.Loader;
all to:
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
Now the TMDB.org API has a request limit of 40 requests per 10 seconds.
https://developers.themoviedb.org/3/getting-started/request-rate-limiting
Because of this, your Loader is not even completing everything and is throwing an exception. I would suggest breaking up when you call the videos and reviews into the MovieActivity by creating another AsyncTaskLoader there and calling each when the details screen loads.
You could also technically add a Thread.sleep(300) or less to your AsyncTaskLoader but it makes it seriously slow. In other words, you would have to push the data beyond the 10-second mark to load completely.
Now, with that and the changes we have made, everything does survive config changes such as screen rotation.
If you want the data to survive any further you will have to persist the data somehow. Like saving the json response as a string in onSaveInstanceState or saving the JSon String to the database you created.
****Working code posted****
I am trying to update buttons where the text will be dynamically programmed from an ArrayList. The data is being retrieved from mySQL. I can get the data in and fill the array with what I need (familyMemberArray). However for some reason when the information is gathered, the program does not go on to implementing the "trending" array or the rest of the layout programming, after the array information has been produced.
I need to formulate the data first so I know how big the array is to create the amount of buttons necessary. If I call in a basic String array it populates the buttons just fine. I remember being stuck on this problem on a uni project and ended up giving up because I just could not get it to work and time was ticking. Please put me out of my misery
public class TrendingMealsFragment extends Fragment {
private TableRow tr;
//SQLite Database
private static final String SELECT_SQL = "SELECT * FROM family_account";
private SQLiteDatabase db;
private Cursor c;
private static final String DATABASE_NAME = "FamVsFam.db";
// Logging
private final String TAG = this.getClass().getName();
private static final String EXTRA_CHALLENGE_ID = "boo.famvsfam.challenge_id";
//Results
private JSONArray resultFamilyMember;
private String dbID;
public static final String JSON_ARRAY = "result";
private List<String> familyMemberArray;
ArrayAdapter<String> adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
openDatabase();
setHasOptionsMenu(true);
c = db.rawQuery(SELECT_SQL, null);
c.moveToFirst();
getRecords();
}
protected void openDatabase() {
db = getActivity().openOrCreateDatabase(DATABASE_NAME, android.content.Context.MODE_PRIVATE, null); // db = SQLiteDatabase.openOrCreateDatabase("FamVsFam", Context.MODE_PRIVATE, null);
}
protected void getRecords() {
dbID = c.getString(0);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getData();
/** Declaring an ArrayAdapter to set items to ListView */
familyMemberArray = new ArrayList<>();
//Menu
setHasOptionsMenu(true);
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
View view = inflater.inflate(R.layout.activity_resturants, container, false);
AppCompatActivity activity = (AppCompatActivity) getActivity();
activity.getSupportActionBar();
/**
ArrayList<String> trending1 = new ArrayList<String>() {
{
add("one");
add("two");
add("three");
add("four");
add("five");
add("six");
add("seven");
add("eight");
add("nine");
add("ten");
add("eleven");
}
};*/
ArrayList<String> trending = new ArrayList<String>() {
{
for(int i = 0; i < familyMemberArray.size() ; i++){
add(familyMemberArray.get(i));
}}
};
// LAYOUT SETTING 1
RelativeLayout root = new RelativeLayout(getActivity());
// root.setId(Integer.parseInt(MEAL_SELECTION_ID));
LayoutParams param1 = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
root.setFitsSystemWindows(true);
}
root.setLayoutParams(param1);
//LAYOUT SETTINGS 2 - TOP BANNER - WITH PAGE HEADING
RelativeLayout rLayout1 = new RelativeLayout(getActivity());
LayoutParams param2 = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
float topBannerDim = getResources().getDimension(R.dimen.top_banner);
param2.height = (int) topBannerDim;
param2.addRule(RelativeLayout.BELOW, root.getId());
int ele = (int) getResources().getDimension(R.dimen.elevation);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
rLayout1.setElevation(ele);
}
rLayout1.setBackgroundColor(Color.parseColor("#EEEBAA"));
rLayout1.setLayoutParams(param2);
//TEXT VIEW
TextView text1 = new TextView(getActivity());
text1.setText(R.string.diet_req);
LayoutParams param3 = new LayoutParams(
LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
param3.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
text1.setTextColor(Color.parseColor("#8A1F1D"));
text1.setTypeface(Typeface.DEFAULT_BOLD);
text1.setLayoutParams(param3);
//LAYOUT SETTINGS 4
RelativeLayout rLayout4 = new RelativeLayout(getActivity());
LayoutParams param5 = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
topBannerDim = getResources().getDimension(R.dimen.top_banner);
param5.height = (int) topBannerDim;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
param5.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.ALIGN_START);
}
param5.addRule(RelativeLayout.BELOW, rLayout1.getId());
rLayout4.setId(R.id.id_relative_4);
rLayout4.setBackgroundColor(Color.parseColor("#EEEBAA"));
rLayout4.setLayoutParams(param5);
//LAYOUT SETTINGS 5
TableLayout rLayout5 = new TableLayout(getActivity());
rLayout5.setOrientation(TableLayout.VERTICAL);
LayoutParams param7 = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
param7.addRule(RelativeLayout.BELOW, rLayout4.getId());
rLayout5.setBackgroundColor(Color.parseColor("#EEEBAA"));
rLayout5.setLayoutParams(param7);
// List<ToggleButton> togButtStore = new ArrayList<ToggleButton>();
int i = 0;
while (i < trending.size()) {
if (i % 3 == 0) {
tr = new TableRow(getActivity());
rLayout5.addView(tr);
}
ToggleButton toggleBtn = new ToggleButton(getActivity());
toggleBtn.setText(trending.get(i));
toggleBtn.setId(i);
toggleBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Context context = getActivity().getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
} else {
// The toggle is disabled
}
}
});
tr.addView(toggleBtn);
i++;
}
//LAYOUT SETTINGS 6
FrameLayout youBeenFramed = new FrameLayout(getActivity());
LayoutParams param8 = new LayoutParams(
LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT);
param8.addRule(RelativeLayout.BELOW, rLayout5.getId());
youBeenFramed.setBackgroundColor(Color.parseColor("#EEEBAA"));
root.addView(youBeenFramed);
root.addView(rLayout1);
rLayout1.addView(text1);
root.addView(rLayout4);
root.addView(rLayout5);
getActivity().setContentView(root);
return view;
}
public void getData() {
//// TODO: 03/08/2016 Progress Dialogs : on getting data
// final ProgressDialog loading = ProgressDialog.show(getActivity(), "Loading Data", "Please wait...", false, false);
StringRequest strReq = new StringRequest(Request.Method.POST,
PHPConfigURLS.URL_ALL_FAMILY_MEMBERS, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Login Response: " + response.toString());
JSONObject j = null;
try {
// loading.dismiss();
//Parsing the fetched Json String to JSON Object
j = new JSONObject(response);
//Storing the Array of JSON String to our JSON Array
resultFamilyMember = j.getJSONArray(JSON_ARRAY);
//Calling method getStudents to get the students from the JSON Array
getDBFamilyName(resultFamilyMember);
} catch (JSONException e) {
// JSON error
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() {
String id = dbID;
// Posting params to register url
Map<String, String> params = new HashMap<String, String>();
params.put("id", id);
// params.put("email", email);
// params.put("password", password);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
//Adding request to the queue
requestQueue.add(strReq);
}
private void getDBFamilyName(JSONArray j) {
//Traversing through all the items in the json array
for (int i = 0; i < j.length(); i++) {
FamilyAccount familyMember = new FamilyAccount();
try {
//Getting json object
JSONObject json = j.getJSONObject(i);
familyMember = new FamilyAccount();
familyMember.setName(json.getString("name"));
familyMember.setID(json.getInt("id"));
} catch (JSONException e) {
e.printStackTrace();
}
//Adding the title of the challenge to array list
familyMemberArray.add(familyMember.getName());
}
}
}
Thanks in advance
for some reason when the information is gathered, the program does not go on to implementing the "trending" array or the rest of the layout programming, after the array information has been produced.
That's because the layout doesn't "dynamically" update when you call this when the request finishes.
familyMemberArray.add(familyMember.getName());
You'll have to clear the view, and redo all the view adding again, or "extract" all the view generation code into it's own method that you can call with the parameter of your ArrayList.
Basically, everything between // LAYOUT SETTING 1 and return view (non-inclusive) needs to be moved into a public void generateView(ArrayList<String> familyMemberArray) method that can optionally return the root View that was generated, if necessary.
Then, at the end of getFamilyName(), outside the loop, call that method with your ArrayList.
I need to formulate the data first so I know how big the array is to create the amount of buttons necessary.
I'm not sure I see where you are doing that. Unless you mean here
while (i < trending.size()) {
Which, instead, trending is an entirely different list reference than familyMemberArray, so it won't update either. Though, it contains the exact same data?
ArrayList<String> trending = new ArrayList<String>() {
{
for(int i = 0; i < familyMemberArray.size() ; i++){
add(familyMemberArray.get(i));
}}
};
That block of code looks a bit odd, considering the ArrayList constructor already provides that functionality
ArrayList<String> trending = new ArrayList<String>(familyMemberArray);
*****WORKING CODE****** Credit to cricket_007
FIELDS
public class TrendingMealsFragment extends Fragment {
// Logging
private final String TAG = this.getClass().getName();
//Results
private JSONArray resultFamilyMember;
public static final String JSON_ARRAY = "result";
private ArrayList<String> familyMemberArray;
//Layout
private TableRow tr;
OnCreateView()
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_resturants, container, false);
generateView(familyMemberArray);
getData();
return view;
}
GetData()
public void getData() {
StringRequest strReq = new StringRequest(Request.Method.POST,
PHPConfigURLS.URL_ALL_FAMILY_MEMBERS, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Login Response: " + response.toString());
JSONObject j = null;
try {
//Parsing the fetched Json String to JSON Object
j = new JSONObject(response);
//Storing the Array of JSON String to our JSON Array
resultFamilyMember = j.getJSONArray(JSON_ARRAY);
//Calling method getStudents to get the students from the JSON Array
getDBFamilyName(resultFamilyMember);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}) {
#Override
protected Map<String, String> getParams() {
String id = dbID;
Map<String, String> params = new HashMap<String, String>();
params.put("id", id);
return params;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
//Adding request to the queue
requestQueue.add(strReq);
}
getDBFamilyName()
private void getDBFamilyName(JSONArray j) {
//Traversing through all the items in the json array
for (int i = 0; i < j.length(); i++) {
FamilyAccount familyMember = new FamilyAccount();
try {
//Getting json object
JSONObject json = j.getJSONObject(i);
familyMember = new FamilyAccount();
familyMember.setName(json.getString("name"));
familyMember.setID(json.getInt("id"));
} catch (JSONException e) {
e.printStackTrace();
}
//Adding the title of the challenge to array list
familyMemberArray.add(familyMember.getName());
generateView(familyMemberArray);
}
}
generateView()
public View generateView(ArrayList<String> familyMemberArray) {
...
rLayout5.setLayoutParams(param7);
//Create Buttons
int i = 0;
while (i < familyMemberArray.size()) {
if (i % 3 == 0) {
tr = new TableRow(getActivity());
rLayout5.addView(tr);
}
ToggleButton toggleBtn = new ToggleButton(getActivity());
toggleBtn.setText(familyMemberArray.get(i));
toggleBtn.setId(i);
toggleBtn.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Context context = getActivity().getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
} else {
// The toggle is disabled
}
}
});
tr.addView(toggleBtn);
i++;
}
...
root.addView(rLayout5);
getActivity().setContentView(root);
return root;
}
}
Below is the code which will display the list of name in the list view.
I want to filter the list view based on the input of search textbox.
I have added the addTextChangedListener method for the edittext. But I am facing an error in getFilter() method as "can't resolve". As per the google I found the getFilter() method work on ArrayAdapter. I want to know how can I make getFilter() method work with ListAdapter.
Please can anyone let me know.
package com.smoothbalance.smothbalance;
public class AddedClientList extends CommonDrawer {
EditText searchTextBox;
ListAdapter adapter;
ListView addedlistofclient;
// JSON Nodes
private static final String TAG_CONTACTS = "data";
private static final String TAG_ID = "id";
private static final String TAG_FULL_NAME = "full_name";
private static final String TAG_EMAIL = "email";
//JSON array
JSONArray json_data = null;
// Hashmap for ListView
ArrayList<HashMap<String, String>> dataList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater layoutInflater = (LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = layoutInflater.inflate(R.layout.activity_added_client_list, null, false);
mDrawerLayout.addView(view, 0);
addedlistofclient = (ListView) findViewById(R.id.listView_Added_Client);
searchTextBox = (EditText) findViewById(R.id.Search_added_clients);
dataList = new ArrayList<HashMap<String, String>>();
if (CommonFunctions.isNetworkAvailable(getBaseContext())) {
params.add(new BasicNameValuePair("", user_id));
new Added_client_list().execute();
} else {
Toast.makeText(getApplicationContext(), "Network Not Available... \n Please check Your Wifi Connection or Mobile Network", Toast.LENGTH_LONG).show();
}
searchTextBox.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
AddedClientList.this.adapter.getFilter().filter(s);
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
private class Added_client_list extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
}
#Override
protected String doInBackground(String... param) {
String network_error = null;
String url = getString(R.string.getClientlist) + user_id + "/Clients";
ServiceHandler serviceHandler = new ServiceHandler();
String jsonStr = serviceHandler.makeServiceCall(url, ServiceHandler.GET);
Log.d("Response: ", "> " + jsonStr);
network_error = jsonStr;
if (jsonStr != null) {
try {
JSONObject jsonObject = new JSONObject(jsonStr);
// getting json array node
json_data = jsonObject.getJSONArray(TAG_CONTACTS);
for (int i = 0; i < json_data.length(); i++) {
JSONObject c = json_data.getJSONObject(i);
String id = c.getString(TAG_ID);
String full_name = c.getString(TAG_FULL_NAME);
String email = c.getString(TAG_EMAIL);
// tmp hashmap for single data
HashMap<String, String> data = new HashMap<String, String>();
// adding each child node to HashMap key => value
data.put(TAG_ID, id);
data.put(TAG_FULL_NAME, full_name);
data.put(TAG_EMAIL, email);
// adding contact to contact list
dataList.add(data);
}
} catch (Exception e) {
e.printStackTrace();
}
}
return network_error;
}
#Override
protected void onPostExecute(String aVoid) {
adapter = new SimpleAdapter(AddedClientList.this, dataList, R.layout.customelistview, new String[]
{TAG_FULL_NAME, TAG_EMAIL,}, new int[]{R.id.details, R.id.serviceData});
addedlistofclient.setAdapter(adapter);
}
}
As Luksprog mentioned in the comment, ListAdapter is not filterable, you would have either have to create a customAdapter by extending the listadapter and implementing filterable in that object, or use an adapter provided by the sdk that implementals filterable
Im trying to return an ArrayList from the AsyncTask class back to the MainAcitivity class and then use this arraylist to fill the gridview in MainActivity.
The parseURL takes a String paramater to parse the url. And parseURL is executed when the user clicks the button. The code i have compiles and run but the gridview is not populated after triggering the button event and pressing the button twice crashes the app.
EDIT: After adding loop callback, it stops crashing but it still wont populate the gridview. The ArrayList object that i want to populate the gridview is in this format 10,John,Smith
Here is my code for MainActivity (using Stanislav Bodnar suggestion)
private GridView grid1;
private ArrayAdapter<String> adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initalized the grid and adapter
grid1 = (GridView)findViewById(R.id.gridView1);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
grid1.setAdapter(adapter);
}
public void onButtonClick(View v) {
EditText textInput = (EditText) findViewById(R.id.editText1);
String code = textInput.getText().toString();
new parseURL() {
#Override
protected void onPostExecute(List<String> list) {
//use the list from parseURL to fill grid view
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
gridView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}.execute(code);
ParseURL class
public class parseURL extends AsyncTask<String, Void, List<String>> {
protected List<String> doInBackground(String... params) {
List<String> str = new ArrayList<String>();
try {
Document doc = Jsoup.connect("http://www.mywebsite.com/id/" + params).get();
Elements row1 = doc.select("table");
Elements row2 = doc.select("td");
Elements row3 = doc.select("td");
for (int i = 0; i < row1.size(); i++) {
str.add(row1.get(i).text() + "," + row2.get(i).text() + "," + row2.get(i).text());
}
return str;
} catch (Exception e) {
return new ArrayList<String>();
}
}
You can add loading callback.
public void onButtonClick(View v) {
EditText textInput = (EditText) findViewById(R.id.editText1);
String code = textInput.getText().toString();
new parseURL() {
#Override
protected void onPostExecute(List<String> list) {
//use the list from parseURL to fill grid view
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
gridView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}.execute(code);
}
Asynctask:
public class parseURL extends AsyncTask<String, Void, List<String>> {
protected List<String> doInBackground(String... params) {
List<String> str = new ArrayList<String>();
try {
Document doc = Jsoup.connect("http://www.mywebsite.com/id/" + params).get();
Elements row1 = doc.select("table");
Elements row2 = doc.select("td");
Elements row3 = doc.select("td");
for (int i = 0; i < row1.size(); i++) {
str.add(row1.get(i).text() + "," + row2.get(i).text() + "," + row2.get(i).text());
}
return str;
} catch (Exception e) {
return new ArrayList<String>();
}
}
}
Supplement
If array list that returns by onPostExecute is not empty your grid will be populated in the next way each cell will have string 10,John,Smith. Please check that method doInBackground does not catch some exception and fills array list correctly.
Next if you want to do a table view where 1 row will contain 3 columns 10 | John | Smith then parse data into object structure:
class Person {
private int id;
private String firstName;
private String lastName;
}
Then change method doInBackground to return array list of Person objects.
Create custom adapter (extend BaseAdapter) where init view using Person object.
View will be as LinearLayout with horizontal orientation which will contain 3 TextView with Layout Weight (android:layout_weight="0.3" - set in each TextView, you can change this value). Then use ListView instead of GridView. Each row of list view will contain 1 Person.
The AsyncTask is by definition asynchronous. Your code handles it like it was synchronous.
Move
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
gridView.setAdapter(adapter);
adapter.notifyDataSetChanged();
into the setList method.
Also, passing around the MainActivity feels a bit shaky. What happens if the Activity is destroyed during the async-task?
Instead, make the AsyncTask a private inner class or an anonymous class in MainActivity
And of course you will need to initialize your list before you populate it.
Don't do gridview.setAdapter() twice. There are a few problems with that code. As P-a Bäckström wrote:
Also, passing around the MainActivity feels a bit shaky. What happens if the Activity is destroyed during the async-task? Instead, make the AsyncTask a private inner class or an anonymous class in MainActivity
You need to fix that too. Now comes the updating part:
Declare a global Handler like this:
private final Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
if(msg.what == 1) {
List<String> list = (List) msg.obj;
adapter.insert(list);
adapter.notifyDataSetChanged();
}
}
};
Then in onPostExecute() send your data to the UI thread using the handler and update the gridview:
protected void onPostExecute(List<String> list) {
handler.obtainMessage(1, list);
}
try this:
Mainactivity.class
private GridView grid1;
private ArrayAdapter<String> adapter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initalized the grid and adapter
grid1 = (GridView)findViewById(R.id.gridView1);
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
grid1.setAdapter(adapter);
}
public void onButtonClick(View v) {
EditText textInput = (EditText) findViewById(R.id.editText1);
String code = textInput.getText().toString();
new parseURL(this).execute(code);
}
public void onBackgroundTaskCompleted(List<String> result) {
// TODO Auto-generated method stub
Log.i(TAG, "onBackgroundTaskCompleted List: "+result);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
gridView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
Asynctask:
public class parseURL extends AsyncTask<String, Void, List<String>> {
MainActivity caller;
public Scheduler(MainActivity mainActivity) {
// TODO Auto-generated constructor stub
this.caller = mainActivity;
}
protected void onPostExecute(List<String> result) {
caller.onBackgroundTaskCompleted(result);
}
protected List<String> doInBackground(String... params) {
List<String> str = new ArrayList<String>();
try {
Document doc = Jsoup.connect("http://www.mywebsite.com/id/" + params).get();
Elements row1 = doc.select("table");
Elements row2 = doc.select("td");
Elements row3 = doc.select("td");
for (int i = 0; i < row1.size(); i++) {
str.add(row1.get(i).text() + "," + row2.get(i).text() + "," + row2.get(i).text());
}
return str;
} catch (Exception e) {
return new ArrayList<String>();
}
}
}