This question has been answered before, but the solutions doesn't seem to work for me. I would like to know what the best way is to save an ArrayList.
I generate an ArrayList with all the installed applications on the phone. This list is shown in a ListView where the user can (de)select apps. This is all working fine. What I would like is that the Arraylist gets saved when the user presses a save button or when the activity calls onPause().
When the user returns to the list the user will see the list the way he saved/left it.
Here is my code:
onCreate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_app_list);
loadApps();
loadListView();
addClickListener();
}
loadApps
private void loadApps(){
manager = getPackageManager();
apps = new ArrayList<AppDetail>();
if(apps.size()==0) {
Intent i = new Intent(Intent.ACTION_MAIN, null);
i.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> availableActivities = manager.queryIntentActivities(i, 0);
for (ResolveInfo ri : availableActivities) {
AppDetail app = new AppDetail();
app.label = ri.loadLabel(manager);
app.name = ri.activityInfo.packageName;
app.icon = ri.activityInfo.loadIcon(manager);
app.allowed = false;
apps.add(app);
}
Log.i("applist", apps.toString());
}
}
AppDetail.class
public class AppDetail {
CharSequence label;
CharSequence name;
Drawable icon;
Boolean allowed;
loadListView
private void loadListView(){
list = (ListView)findViewById(R.id.apps_list);
adapter = new ArrayAdapter<AppDetail>(this, R.layout.list_item, apps) {
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = getLayoutInflater().inflate(R.layout.list_item, null);
}
ImageView appIcon = (ImageView)convertView.findViewById(R.id.item_app_icon);
appIcon.setImageDrawable(apps.get(position).icon);
TextView appLabel = (TextView)convertView.findViewById(R.id.item_app_label);
appLabel.setText(apps.get(position).label);
TextView appName = (TextView)convertView.findViewById(R.id.item_app_name);
appName.setText(apps.get(position).name);
if(list.isItemChecked(position)){convertView.setBackgroundColor(getResources().getColor(R.color.green));}
if(!list.isItemChecked(position)){convertView.setBackgroundColor(getResources().getColor(R.color.white));}
return convertView;
}
};
list.setAdapter(adapter);
list.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
}
addClickListener
private void addClickListener() {
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> av, View v, int pos,
long id) {
checked = list.getCheckedItemPositions();
ArrayList<AppDetail> allowedApps = new ArrayList<>();
for (int i = 0; i < checked.size(); i++) {
// Item position in adapter
int position = checked.keyAt(i);
// Add sport if it is checked i.e.) == TRUE!
if (checked.valueAt(i)) {
allowedApps.add(adapter.getItem(position));
}
}
adapter.notifyDataSetChanged();
Log.i("", allowedApps.toString());
}
});
}
At this moment I'm creating two lists:
List: list of all apps
AllowedApps: list of checked (allowed) apps, to use in an other activity
If you need saving your list when activity is paused, you have several ways to do it. First you need define the private list field in your activity.
private ArrayList<AppDetail> allowedApps;
1) Make AppDetail serializable and use onSaveInstanceState
public class AppDetail implements Serializable {
CharSequence label;
CharSequence name;
Drawable icon;
Boolean allowed;
}
---------------- EDIT -----------------
I would change Drawable icon field for int icon.
In your loadApps() method change the setence app.icon = ri.activityInfo.getIconResource();
In yout loadListView method change the setence appIcon.setImageResource(apps.get(position).icon);
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putSerializable("allowedApps", allowedApps);
}
Retrieve the list in onCreate method
if (savedInstanceState != null) {
allowedApps = (List<AppDetail>)savedInstanceState.getSerializable("allowedApps");
}else{
allowedApps = new ArrayList<AppDetail>();
}
2) Use onRetainCustomNonConfigurationInstance
Return the list in onRetainCustomNonConfigurationInstance
#Override
public Object onRetainCustomNonConfigurationInstance() {
return allowedApps;
}
Retrieve the list in onCreate method
Object allowedApps= getLastCustomNonConfigurationInstance();
if (allowedApps != null) {
this.allowedApps = (List<AppDetail>) allowedApps;
}else{
this.allowedApps = new ArrayList<AppDetail>();
}
I think you are looking for something like "Parcelable". It can save any ArrayList and retrieve back when you need it just like the Shared Preferences.
Please have a look here,
How to save custom ArrayList on Android screen rotate?
ArrayList is serializable. Save it as a serializable object in file on storage
Related
What I want to do is to show the same selected items on a recycler view even after the activity has been closed and only change items color when I again click on it. For now I have achieved changing the color on click but the state doesn't get saved?
This is my adapter:
public class LightsRecyclerViewAdapter extends
RecyclerView.Adapter<LightsRecyclerViewAdapter.ViewHolder> {
// private List<Integer> mViewColors;
private List<String> mAnimals;
private LayoutInflater mInflater;
private ItemClickListener mClickListener;
// data is passed into the constructor
LightsRecyclerViewAdapter(Context context, List<String>
animals) {
this.mInflater = LayoutInflater.from(context);
this.mAnimals = animals;
}
// inflates the row layout from xml when needed
#Override
#NonNull
public ViewHolder onCreateViewHolder(#NonNull ViewGroup
parent, int viewType) {
View view = mInflater.inflate(R.layout.item, parent,
false);
return new ViewHolder(view);
}
// binds the data to the view and textview in each row
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int
position) {
// int color = mViewColors.get(position);
String animal = mAnimals.get(position);
// holder.myView.setBackgroundColor(color);
holder.myTextView.setText(animal);
}
// total number of rows
#Override
public int getItemCount() {
return mAnimals.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
View myView;
TextView myTextView;
ViewHolder(View itemView) {
super(itemView);
// myView = itemView.findViewById(R.id.colorView);
myTextView =
itemView.findViewById(R.id.tvAnimalName);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (mClickListener != null)
mClickListener.onItemClick(view, getAdapterPosition());
}
}
// convenience method for getting data at click position
public String getItem(int id) {
return mAnimals.get(id);
}
// allows clicks events to be caught
public void setClickListener(ItemClickListener
itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface ItemClickListener {
void onItemClick(View view, int position);
}
}
And this is my activity:
public class DevicesList extends AppCompatActivity implements
LightsRecyclerViewAdapter.ItemClickListener{
private LightsRecyclerViewAdapter adapter,adapter1;
TextView title;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_devices_list);
title = (TextView)findViewById(R.id.textGrid);
// data to populate the RecyclerView with
ArrayList<Integer> viewColors = new ArrayList<>();
viewColors.add(Color.BLUE);
viewColors.add(Color.YELLOW);
viewColors.add(Color.MAGENTA);
viewColors.add(Color.RED);
viewColors.add(Color.BLACK);
ArrayList<String> Lab1LightsList = new ArrayList<>();
Lab1LightsList.add("Light 1");
Lab1LightsList.add("Light 2");
Lab1LightsList.add("Light 3");
Lab1LightsList.add("Light 4");
Lab1LightsList.add("Light 5");
ArrayList<String> Lab1ACList = new ArrayList<>();
Lab1ACList.add("AC 1");
Lab1ACList.add("AC 2");
Lab1ACList.add("AC 3");
Lab1ACList.add("AC 4");
Lab1ACList.add("AC 5");
ArrayList<String> Lab2LightsList = new ArrayList<>();
Lab2LightsList.add("Light 1");
Lab2LightsList.add("Light 2");
Lab2LightsList.add("Light 3");
Lab2LightsList.add("Light 4");
Lab2LightsList.add("Light 5");
Lab2LightsList.add("Light 6");
ArrayList<String> Lab2ACList = new ArrayList<>();
Lab2ACList.add("AC 1");
Lab2ACList.add("AC 2");
Lab2ACList.add("AC 3");
Lab2ACList.add("AC 4");
// set up the RecyclerView
RecyclerView recyclerView = findViewById(R.id.list1);
RecyclerView recyclerView1 =findViewById(R.id.list2);
LinearLayoutManager horizontalLayoutManagaer
= new LinearLayoutManager(DevicesList.this, LinearLayoutManager.HORIZONTAL, false);
LinearLayoutManager horizontalLayoutManager
= new LinearLayoutManager(DevicesList.this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(horizontalLayoutManagaer);
recyclerView1.setLayoutManager(horizontalLayoutManager);
Intent mIntent = getIntent();
int intValue = mIntent.getIntExtra("labno", 0);
if(intValue==0) {
adapter = new LightsRecyclerViewAdapter(this, Lab1LightsList);
adapter1 = new LightsRecyclerViewAdapter(this, Lab1ACList);
adapter.setClickListener(this);
adapter1.setClickListener(this);
recyclerView.setAdapter(adapter);
recyclerView1.setAdapter(adapter1);
}
if(intValue==1) {
adapter = new LightsRecyclerViewAdapter(this, Lab2LightsList);
adapter1 = new LightsRecyclerViewAdapter(this, Lab2ACList);
adapter.setClickListener(this);
adapter1.setClickListener(this);
recyclerView.setAdapter(adapter);
recyclerView1.setAdapter(adapter1);
}
}
#Override
public void onItemClick(View view, int position) {
Toast.makeText(this, "You clicked " +
adapter.getItem(position) + " on item position " + position,
Toast.LENGTH_SHORT).show();
view.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
}
}
Please help on this.
Create one selected item position list and store it in prefs when an app goes to background or closed. Load that list when launching an app and compare that list in an adapter's onBindViewHolder's position parameter and marks it selected/unselected based on a comparison.
As per my understandings about your question, you want to save the state of the selected items even after the app is closed, and then you want to reload it whenever the app is launched again. You need to refer to this link Android Save Data
For the above solution, there can be various ways to save state, I am mentioning a few below:
Use SQLite Database to save the selected items. Then, whenever the app is loaded, fetch all the selected data from the DB and then mark them selected with whatever colour you want on the list.
You can also use Shared Preferences, to store the selection. And, same as above, you can reload the data when the app is launched.
You can also store the data in a specific format, maybe CSV, JSON, XML etc., in a file and save it either in Internal Storage or External Storage of the device. And when the app is launched, fetch all the selected values from the file and process accordingly.
You can also use a web server, Firebase Storage, or other cloud storage services to save the data and then fetch the data on new app launch.
Do note: All these techniques require you to save the state before the app is closed. So it is better to store the states, either on click of the item, or onPause method of the activity.
If you face any problems with these solutions, you can post another comment and I will give it a look.
Save these clicked item position in a hashmap in Shareprefence. suppose u close the activity after u coming back the activity just pass the saved list with ur data in adapter and compare the shareprefence list with ur data list if position or data match than make the itemview layout colored.
// save clicked item is a list and save it sharePreference.
List<Integer> clikedList = new ArrayList<>();
if (clicked item){
ClikedList.add(position)
}
String value = gson.toJson(list);
SharedPreferences prefs = context.getSharedPreferences("mylist",
Context.MODE_PRIVATE);
Editor e = prefs.edit();
e.putString("list", value);
e.commit();
// for getting cliked position list from SharePreference
SharedPreferences prefs = context.getSharedPreferences("mylist",
Context.MODE_PRIVATE);
String value = prefs.getString("list", null);
GsonBuilder gsonb = new GsonBuilder();
Gson gson = gsonb.create();
MyObject[] list = gson.fromJson(value, MyObject[].class);
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// suppose clicked position 4 u get from shaved cliked list
in here u neddd to retreive cliked list position and clored those item
int select = 4;
if (select == position) {
holder.itemView.setBackgroundColor(Color.BLUE);
Toast.makeText(context, "" + position, Toast.LENGTH_SHORT).show();
} else {
holder.itemView.setBackgroundColor(Color.parseColor("#214F4B"));
Toast.makeText(context, "" + position, Toast.LENGTH_SHORT).show();
}
holder.tv_title.setText(data.get(position));
}
I am working on a project where I have a let's say 5x5 grid of TextViews and I want to check if an entire row or column has equal elements. I am using an Adapter class to inflate my gridview with simply one textview element. Here is the code that I have tried but I cannot seem to make it work:
final int size = gridView.getCount(); //25
int temp = 0;
for (int i = 0; i < size; i++) {
ViewGroup gridChild = (ViewGroup) gridView.getChildAt(i);
childSize = gridChild.getChildCount();
for (int j = 0; j < childSize; j++) {
if (gridChild.getChildAt(j) instanceof TextView &&
((TextView) gridChild.getChildAt(j)).getText().toString().equals("x")) {
temp++;
}
The thing is when i tried to debug, debugger showed null values for childSize variable and could not properly get the value from getChildAt. Basically, what I am trying to do is get inside the if statement. Also this is the first time I am working with ViewGroup calss, and the methods that I call. Any help would be appreciated.
Edit:I am looking for a way to do this outside the getView method in the adapter class and not in a onClick method as well. (Code sample answers would be highly appreciated). Also, the getChildAt method call returns null so the code I have shown would not work because I am assigning a null value to the gridChild.
This is the onClick that I use for the TextViews:
`
public void numberFill(View view) {
if (((TextView) view).getText().toString().isEmpty()) {
((TextView) view).setText(String.valueOf(numbCounter + 1));
numbCounter++;
}
else if (!((TextView) view).getText().toString().isEmpty() && numbCounter >= 16) {
((TextView) view).setText("x");
}
}
This is my adapter class:
public class GridAdapter extends BaseAdapter {
private final Context mContext;
private String[] numbers;
public GridAdapter(Context context, String[] numbers) {
this.mContext = context;
this.numbers = numbers;
}
#Override
public int getCount() {
return numbers.length;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public Object getItem(int position) {
return numbers[position];
//return null;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater)
mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
if (convertView == null) {
gridView = new View(mContext);
gridView = inflater.inflate(R.layout.textview_layout, null);
TextView textView = (TextView) gridView.findViewById(R.id.cell);
textView.setText(numbers[position]);
} else {
gridView = (View) convertView;
}
return gridView;
}
}
numberFill reworked:
public void numberFill(View view) {
int index = (Integer) view.getTag();
if (numbers[index].toString().isEmpty()) {
numbers[index] = String.valueOf(numbCounter + 1);
numbCounter++;
}
else if (!numbers[index].toString().isEmpty() && numbCounter >= 25) {
numbers[index] = "x";
}
gridAdapter.notifyDataSetChanged();
}
`
When using an AdapterView – such as your GridView – you generally don't want to directly access and manipulate its child Views outside of its Adapter. Instead, the dataset backing the Adapter should be updated, and the GridView then refreshed.
In your case, you presumably have a setup similar to this in your Activity:
private GridAdapter gridAdapter;
private String[] numbers;
#Override
protected void onCreate(Bundle savedInstanceState) {
...
numbers = new String[25];
gridAdapter = new GridAdapter(this, numbers);
}
Here, the numbers array is what you want to directly modify, rather than the text on the GridView's child TextViews. That array is then easily iterated over to do your row and column value checks.
Since the array will be modified in the Activity, we need a way to pass the clicked TextView's position in the Adapter to the Activity's click method, as we'll need it to access the correct array element. For this, we can utilize the tag property available on all View's, via the setTag() and getTag() methods. For example, in GridAdapter's getView() method:
...
TextView textView = (TextView) gridView.findViewById(R.id.cell);
textView.setText(numbers[position]);
textView.setTag(position);
...
In the click method, the position can be easily retrieved with getTag(), and used as the index to get the clicked TextView's text from the numbers array. You can then do the necessary processing or calculation with that text, set the modified value back to the array element, and trigger a refresh on the Adapter.
public void numberFill(View view) {
int index = (Integer) view.getTag();
// Do your processing with numbers[index]
numbers[index] = "new value";
gridAdapter.notifyDataSetChanged();
}
The notifyDataSetChanged() call will cause the GridView to update its children, and your new value will be set in the appropriate TextView. The numbers array now also has the current values, and is readily available in the Activity to perform the necessary checks there.
I've searched all the posts I can find, and none seem to help with my situation. I have an android project that uses web services to pull down hourly weather data and populate a listView with the results.
The weird problem I'm having is that when I debug the project on my android phone, the main activity is blank and the listView isn't populated. If I run the project from android studio with my phone locked, and then unlock my phone the app opens on my phone with all of the listView properly formatted and populated.
I feel like it's a race condition issue between the asynctask and the adapter, but I can't seem to resolve it. I tried making my asyncTask an inner private class and calling notifyDataSetChanged on the adapter inside the onPostExecute method, but to no avail. I feel it must be something simple, but I'm relatively new to Android dev, so I'm stuck.
I have three classes that I'll post the pertinent code from
MainActivity.java (onCreate)
public class MainActivity extends ActionBarActivity {
ArrayList<Weather> w = new ArrayList<Weather>();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DownloadWeatherTask myTask = new DownloadWeatherTask(w);
WeatherAdapter myAdapter = new WeatherAdapter(this,w);
ListView l = (ListView) findViewById(R.id.weatherList);
l.setAdapter(myAdapter);
myTask.execute();
}
}
WeatherAdapter.java
public class WeatherAdapter extends ArrayAdapter<Weather>{
public WeatherAdapter(Context context, ArrayList<Weather> weather) {
super(context, R.layout.item_weather, weather);
}
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
Weather forecast = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_weather, parent, false);
}
// Lookup view for data population
TextView tvTime = (TextView) convertView.findViewById(R.id.listTime);
TextView tvDescr = (TextView) convertView.findViewById(R.id.listDescr);
TextView tvTemp = (TextView) convertView.findViewById(R.id.listTemp);
TextView tvHumid = (TextView) convertView.findViewById(R.id.listHumid);
ImageView ivWeather = (ImageView) convertView.findViewById(R.id.weatherImg);
// Populate the data into the template view using the data object
tvTime.setText(forecast.time);
tvDescr.setText(forecast.description);
tvTemp.setText(forecast.temperature+"°(F)");
tvHumid.setText(forecast.humidity+"% humidity");
ivWeather.setImageBitmap(forecast.weatherImg);
// Return the completed view to render on screen
return convertView;
}
}
DownloadWeatherTask.java
public class DownloadWeatherTask extends AsyncTask<Void,Void,Void>{
ArrayList<Weather> data;
public DownloadWeatherTask(ArrayList<Weather> a){
data = a;
}
public ArrayList<Weather> getData() {
return data;
}
protected Void doInBackground(Void...params) {
try {
String website = "http://api.wunderground.com/api/1111111111111/geolookup/q/autoip.json";
URL site = new URL(website);
HttpURLConnection weatherUnderground = (HttpURLConnection) site.openConnection();
weatherUnderground.connect();
JsonParser weatherParser = new com.google.gson.JsonParser();
JsonElement weatherJson = weatherParser.parse(new InputStreamReader((InputStream) weatherUnderground.getContent()));
JsonObject weatherObj = weatherJson.getAsJsonObject();
String zip = weatherObj.get("location").getAsJsonObject().get("zip").getAsString();
String city = weatherObj.get("location").getAsJsonObject().get("city").getAsString();
String state = weatherObj.get("location").getAsJsonObject().get("state").getAsString();
String hourly = "http://api.wunderground.com/api/111111111111/hourly/q/" + state + "/" + city + ".json";
URL hourlySite = new URL(hourly);
HttpURLConnection hourlyConnection = (HttpURLConnection) hourlySite.openConnection();
hourlyConnection.connect();
com.google.gson.JsonParser hourlyParser = new com.google.gson.JsonParser();
JsonElement hourlyWeatherJson = weatherParser.parse(new InputStreamReader((InputStream) hourlyConnection.getContent()));
JsonArray weatherArr = hourlyWeatherJson.getAsJsonObject().get("hourly_forecast").getAsJsonArray();
int l = weatherArr.size();
for (int i = 0; i < l; i++) {
String date = weatherArr.get(i).getAsJsonObject().get("FCTTIME").getAsJsonObject().get("pretty").getAsString();
String temp = weatherArr.get(i).getAsJsonObject().get("temp").getAsJsonObject().get("english").getAsString();
String condition = weatherArr.get(i).getAsJsonObject().get("condition").getAsString();
String humidity = weatherArr.get(i).getAsJsonObject().get("humidity").getAsString();
String iconUrl = weatherArr.get(i).getAsJsonObject().get("icon_url").getAsString();
Bitmap icon = getBitmapFromURL(iconUrl);
data.add(new Weather(date, condition, temp, humidity, icon));
}
} catch (IOException e) {
Log.e("Error: ",e.toString());
}
return null;
}
protected void onPostExecute(Void...params){
}
}
Below are links to my screenshots showing the app not populating the listView, and the app working properly when the program is run while the phone is initially locked.
Any help would be greatly appreciated!!
Thanks
In postExecute(), you need to update the adapter's List and then invoke its notifyDataSetChanged method. I suspect that you were forgetting to update the adapter's data.
The other option is to create a new adapter with the new data, and set the new adapter on the ListView.
I figured out what the issue was! I hadn't added #Override to my onPostExecute() method so it was never being called.
I added the notifyDataSetChanged to my onPostExecute as suggested, which worked once I added the #override to my method.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have develop one application. Here i have to add the value on ArrayList. if i have to click Button means that value have to add on that ArrayList. I have to click another Button means that added list is displaying. How can i do? Please give me solution.
These are my values:
product_id = getIntent().getStringExtra("id");
product_title = getIntent().getStringExtra("title");
product_image = getIntent().getStringExtra("image");
product_price = getIntent().getStringExtra("price");
product_desc = getIntent().getStringExtra("description");
arrayList = new ArrayList<String>();
arrayList.add(product_title);
arrayList.add(product_price);
arrayList.add(product_id);
arrayList.add(product_image);
arrayList.add(product_desc);
I have to add these values on ArrayList while clicking the Button:
valueaddlist = (Button) findViewById(R.id.valueaddlist);
valueaddlist.setOnClickListener(new OnClickListener() {
public void onClick(View v){
Intent intent = new Intent(this,AddedListProducts.class);
intent.putExtra("WishListProducts", arrayList);
startActivity(intent);
}
In the AddedListProducts have to displaying all added products list.
How can i do ?
please give me solution for these ?
EDIT:
This is my AddedListProducts class code:
wishlist_products = (ListView) findViewById(R.id.wishlist_products);
if(getIntent().getExtras() !=null){
WishListProducts = (ArrayList<String>) getIntent().getExtras().getSerializable("WishListProducts");
System.out.println(WishListProducts);
wishlistproductsAdapter = new WishListAdapter(this,WishListProducts);
wishlist_products.setAdapter(wishlistproductsAdapter);
}
In these arraylist am getting values.how can i set the value on adapter file and UI.
This is my adapter file code:
public class WishListAdapter extends BaseAdapter{
WishListAdapter mListViewAdapter;
private Activity mActivity;
private ArrayList<String> mwishlistProducts;
public ImageLoader mImageLoader;
private static LayoutInflater inflater=null;
public WishListAdapter(Activity activity, ArrayList<String> products) {
mActivity = activity;
this.mwishlistProducts=products;
inflater = (LayoutInflater)mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
class ViewHolder{
private ImageView productImageView;
private TextView productTitleView;
private TextView productPriceView;
private TextView productDescView;
public ViewHolder(ImageView productImageView, TextView productTitleView,TextView productPriceView,TextView productDescView) {
super();
this.productImageView = productImageView;
this.productTitleView = productTitleView;
this.productPriceView = productPriceView;
this.productDescView = productDescView;
}
} // ViewHolder-class
public int getCount() {
return mwishlistProducts.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
ViewHolder holder;
final String wishlistproductList = mwishlistProducts.get(position);
if( convertView == null )
{
convertView = inflater.inflate(R.layout.list_product, null);
ImageView productImage=(ImageView)convertView.findViewById(R.id.productimage);
TextView productTitle = (TextView)convertView.findViewById(R.id.producttitle);
TextView productPrice = (TextView)convertView.findViewById(R.id.productprice);
TextView productDesc = (TextView)convertView.findViewById(R.id.productdescription);
holder = new ViewHolder(productImage,productTitle,productPrice,productDesc);
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
convertView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
}
});
holder.productTitleView.setText();
holder.productPriceView.setText();
holder.productDescView.setText();
mImageLoader=new ImageLoader();
mImageLoader.DisplayImage();
return convertView;
}
}
In these holder file what i have to set ????
How can i set that arraylist value here.please help me yaar..
EDIT:
More products is displaying on one listview.
Now i have to click one list item means its go to detail description page.here i have to click button means that product detail value is adding and have to display on AddedListProducts Page.
now i ll go to back and click another product means click button means that product detail also added and have to display on AddedListProducts page with that old added products...
i have to add products from that listview and go to next page and clicking button means have to display that all added products on AddedListProducts page.how can i do ???
Above code ly displaying last added product ly.I want to display all added products on that list.
After getting value from intent:
ArrayList<String> arrayList = new ArrayList<String>();
valueaddlist = (Button) findViewById(R.id.valueaddlist);
valueaddlist.setOnClickListener(new OnClickListener() {
public void onClick(View v){
arrayList.add(product_id);
arrayList.add(product_title);
arrayList.add(product_image);
arrayList.add(product_price);
arrayList.add(product_desc);
}
valuedisplaylist = (Button) findViewById(R.id.valuedisplaylist);
valuedisplaylist.setOnClickListener(new OnClickListener() {
public void onClick(View v){
Intent intent = new Intent(this,AddedListProducts.class);
intent.putStringArrayListExtra("arrayList", (ArrayList<String>) arrayList);
startActivity(intent);
}
May be this will help you.
In your second activity get the arraylist like :
ArrayList<String> ar1=getIntent().getExtras().getStringArrayList("arrayList"); ArrayAdapter<String> arrayAdapter =
new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, ar1);
lv.setAdapter(arrayAdapter);
Then have a look at this question to display arraylist: Populating a ListView using an ArrayList?
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.add(5);
I'm trying to download images for each artist that has music on my phone, then show these images in a GridView. I'm using the lastfm-java library that Last.fm recommends using. The method you call to fetch an artists image is getImageURL(ImageSize size), but before you do this, you need to tell it which artist you want to reference with a String parameter. So, in full it would be something like this:
#Override
protected String doInBackground(Object... arg0) {
Artist artist = Artist.getInfo(artistOrMbid, LASTFM_API_KEY);
return artist.getImageURL(ImageSize.EXTRALARGE);
}
Getting all the artists that are on my phone isn't a problem, you just reference MediaStore. You would do something like this:
private void getArtists() {
String[] projection = new String[] {
MediaStore.Audio.Artists._ID, MediaStore.Audio.Artists.ARTIST,
};
String sortOrder = MediaStore.Audio.Artists.DEFAULT_SORT_ORDER;
Cursor c = getActivity().getContentResolver().query(
MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, projection, null, null, sortOrder);
if (c != null) {
int count = c.getCount();
if (count > 0) {
final int ARTIST_IDX = c.getColumnIndex(MediaStore.Audio.Artists.ARTIST);
for (int i = 0; i < count; i++) {
c.moveToPosition(i);
}
}
c.close();
c = null;
}
}
The Adapter for my GridView isn't anything special, it simply extends BaseAdapter.
Note AQuery is a library I'm using that helps cache and load a Bitmap from a URL.
public class GridViewAdapter extends BaseAdapter {
private final String[] imageURLs;
private final LayoutInflater mInflater;
private final Activity mActivity;
public GridViewAdapter(String[] urls, Activity activity) {
imageURLs = urls;
mActivity = activity;
mInflater = (LayoutInflater)mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return imageURLs.length;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewholder = null;
// Inflate GridView items
if (convertView == null) {
convertView = mInflater.inflate(R.layout.gridview_items, null);
viewholder = new ViewHolder();
viewholder.mImage = (ImageView)convertView.findViewById(R.id.gridview_image);
convertView.setTag(viewholder);
} else {
viewholder = (ViewHolder)convertView.getTag();
}
AQuery aq = new AQuery(convertView);
aq.id(viewholder.mImage).image(imageURLs[position], false, false, 0, 0, null, 0, 0.75f);
return convertView;
}
}
class ViewHolder {
public ImageView mImage;
}
So in full, my AsyncTask is as follows:
public class LastfmArtistGetImageURL extends AsyncTask<Object, Integer, String[]> implements
Constants {
private static final String tag = LastfmArtistGetImageURL.class.getSimpleName();
private GridViewAdapter mGridAdapter;
// Test
private final String[] imageIds = {
"http://userserve-ak.last.fm/serve/252/71875544.png",
"http://userserve-ak.last.fm/serve/252/6258507.jpg",
"http://userserve-ak.last.fm/serve/252/51274303.png",
"http://userserve-ak.last.fm/serve/252/58672183.png",
"http://userserve-ak.last.fm/serve/252/72029714.png",
"http://userserve-ak.last.fm/serve/252/17666215.jpg",
"http://userserve-ak.last.fm/serve/252/63247381.png",
"http://userserve-ak.last.fm/serve/252/33665463.jpg"
};
private final String artistOrMbid;
private final GridView mGridView;
private final Activity mActivity;
public LastfmArtistGetImageURL(String name, GridView gv, Activity activity) {
artistOrMbid = name;
mGridView = gv;
mActivity = activity;
}
#Override
protected String[] doInBackground(Object... arg0) {
Artist artist = Artist.getInfo(artistOrMbid, LASTFM_API_KEY);
Collection<String> col = new ArrayList<String>();
col.add(artist.getImageURL(ImageSize.EXTRALARGE));
return col.toArray(new String[0]);
}
#Override
protected void onPostExecute(String[] result) {
if (result != null)
mGridAdapter = new GridViewAdapter(imageIds, mActivity);
mGridView.setAdapter(mGridAdapter);
super.onPostExecute(result);
}
}
When I call my AsyncTask, I call it in my getArtists() method like this:
new LastfmArtistGetImageURL(c.getString(ARTIST_IDX), mGridView, getActivity())
.execute();
Problem
When I call this, all of the artists images download, but they download one after the other at position 0 of my GridViewAdapter. In other words, one image loads, then next, and so on all in the first position when I need them to be placed into each available position in the GridView. When I return my test String[] in my AsyncTask everything works like it should. All of the images are placed in order in each available space in the GridView.
Question
My question is, how do I return each artist image I download into my GridView correctly and why are the images currently only being loaded at the first position in my GridViewAdapter?
Edit - Shubhayu's answer
I moved setting my GridViewAdapter into my getArtists() method like so. This results in all the images being downloaded (As says LogCat), but only the last one being set in my GridView.
String[] test = new LastfmArtistGetImageURL(c.getString(ARTIST_IDX),
mGridView, getActivity()).execute().get();
mGridAdapter = new GridViewAdapter(test, getActivity());
mGridView.setAdapter(mGridAdapter);
smoak's answer
This results in only the last artist image (by the default order) being downloaded and applied in my GridView.
String[] test = {c.getString(ARTIST_IDX)};
new LastfmArtistGetImageURL(test, mGridView, getActivity()).execute();
Your AsyncTask looks like you are executing it each time for each Artist. Thus, your AsyncTask returns only one Artist's image and your GridView gets that Artists image, then you run the AsyncTask for the next Artist, GridView gets updated with new image and so on. What you need to do is modify your AsyncTask to take a String array of Artist names and loop over them in the doInBackground to get their image's.
// ... SNIPPED
public LastfmArtistGetImageURL(String[] names, GridView gv, Activity activity) {
artistsOrMbids = names;
mGridView = gv;
mActivity = activity;
}
#Override
protected String[] doInBackground(Object... arg0) {
Collection<String> col = new ArrayList<String>();
for (String nameOrMbid : this.artistsOrMbids) {
Artist artist = Artist.getInfo(artistOrMbid, LASTFM_API_KEY);
col.add(artist.getImageURL(ImageSize.EXTRALARGE));
}
return col.toArray(new String[0]);
}
// .... SNIPPED
And pass in all the artist names:
String[] artists = { "The Black Keys", "Rush", "The Allman Brothers" };
new LastfmArtistGetImageURL(artists, mGridView, getActivity()).execute();
here's what is happening, when you pass the test string it has a list of images and hence the gridview shows them properly. but when you use it to download an image for each artist, things go wrong.
Every time you call
new LastfmArtistGetImageURL(c.getString(ARTIST_IDX), mGridView, getActivity()).execute();
it runs the doInBackground(), completes it and then immediately calls the onPostExecute() where it creates a new adapter and passes your result which basically contains a single image of the single call.
So what u need to do is in your asynctask download all the images and then create a single adapter and pass all the images to it. That is not happening currently.
EDIT
If you see the AsyncTask, you will realize that everytime you call it, the string array returns only one image. So instead of returning a string array, return a string.
Next, I would suggest you use an ArrayList in your Adapter instead of a String array.
In your getArtists(), create an ArrayList and everytime you call
new LastfmArtistGetImageURL(test, mGridView, getActivity()).execute();
add the result to your ArrayList. Once you have looped through all the artists, your ArrayList will contain all the images.
Now set it to the Adapter. (You would have t change the adapter a bit if you change it from string to arraylist.)