Alright so this may already be a thread but I still have yet to find a thread that answers my questions!
this is my code.
LayoutInflater inflater = (LayoutInflater)getApplicationContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
So I get an error on"getApplicationContext()"and".getSystemService()" because I don't think they're defined or anything like that but I wouldn't know what to do or where to go to define it...?
someone help pls
This is the actual code for this method:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
String message = myArrayList.get(position);
LayoutInflater inflater = (LayoutInflater)getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View myLayout = inflater.inflate(R.layout.chat_activity, null);
TextView messageTextView = (TextView) myLayout.findViewById(R.id.chat_function);
messageTextView.setText(message);
convertView = myLayout;
return convertView;
and the error is simple and it's basically "Cannot resolve method etc etc" but I don't really know what to do now knowing that that's the error!!
Related
I am fighting for a week now with a "getGroupView(int listPosition, boolean isExpanded, View convertView, ViewGroup parent)" method.
I've found one key thing:
listPosition and convertView are NOT always related
#Override
public View getGroupView(int listPosition, boolean isExpanded, View convertView, ViewGroup parent) {
String listTitle = getGroup(listPosition).toString();
if (convertView == null) {
LayoutInflater layoutInflater = (LayoutInflater) this.context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = layoutInflater.inflate(R.layout.list_group, null);
}
TextView listTitleTextView = (TextView) convertView.findViewById(R.id.listTitle);
Item item = (Item) getGroup(listPosition); //Returns item from ArrayList
// The part behind && should ensure that no wrong passes happen. But they do anyway.
if (item.AllFound() && item.toString(Item.BASE_TITLE_FORMAT).equals(listTitleTextView.getText())){
//listTitleTextView.setBackgroundColor(Color.GREEN);
convertView.setBackgroundColor(Color.GREEN);
}
listTitleTextView.setText(listTitle);
return convertView;
}
What is this:
Background color of convertView (or listTitleTextView) should change to GREEN if item at groupPosition returns TRUE from method AllFound()
A lot of times, the convertView gets colored even though it should not.
But that's just my gibberish. I am willing to rewrite the whole thing.
So how to change (title) view of ExpandableList depending on Object that has created it? (Obviously you cannot depend on listPosition so how should I retrieve the correct object?)
the convertView will be reused, consider all situation
if (item.AllFound() && item.toString(Item.BASE_TITLE_FORMAT).equals(listTitleTextView.getText())){
//listTitleTextView.setBackgroundColor(Color.GREEN);
convertView.setBackgroundColor(Color.GREEN);
} else{
**Add code here to set backgroundColor**
}
Consider the code below:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = (ImageView) convertView; //here
if (imageView == null) {
imageView = (ImageView) inflater.inflate(R.layout.item_gallery_image, parent, false);
}
ImageLoader.getInstance().displayImage(IMAGE_URLS[position], imageView, options);
return imageView;
}
Findbugs plugin from Android Studio is complaining about the first line from the method getview, it says:
Unchecked/unconfirmed cast
This cast is unchecked, and not all instances of the type casted from can be cast to the type it is being cast to. Check that your program logic ensures that this cast will not fail.
Any ideas of how do I resolve this issue?
If you want to please FindBugs you can assert that convertView is an ImageView.
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_gallery_image, parent, false);
}
assert convertView instanceof ImageView : convertView;
ImageLoader.getInstance().displayImage(IMAGE_URLS[position], (ImageView) imageView, options);
return imageView;
}
Not every View is an ImageView, so FindBugs is trying to warn you that the cast may result in a ClassCastException.
However, you actually can't get a ClassCastException because the way convertView works is that you either recieve null or you receive a View previously returned by the getView() method. Since your method always returns an ImageView, everything is fine.
FindBugs finds potential problems with your code, and sometimes they are actually not problems at all.
i think you try to fill every row of a listView or recycle view with image...first you should make layout that contains an image view then you can do it in this way:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
view=inflater.inflate(R.layout.adapter_row,parent,false);
ImageView mImage=(ImageView) view.findViewById(R.id.imageid);
ImageLoader.getInstance().displayImage(IMAGE_URLS[position], mImage, options);
return view;
}
I created a custom expandable list adapter and inside the getGroupView()
and getChildView() i do the following but recieve an error:
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = getActivity().getLayoutInflater()
.inflate(R.layout.expandable_list_parent_row_layout);
}
return convertView;
}
compiler tells me that it cannot find method - getActivity()
Can someone please help? Thanks!
In the adapter constructor, you will have a Context argument. Use this (Activity)context to getLayoutInflater.
Adapter class does not have getActivity() method.
You need to post more of your code - I suspect your accessing this in an Activity and not a Fragment (which provides the method, getActivity())
You need your Context in the code, this is what your code should look like.
LayoutInflater inflater = (LayoutInflater)context.getSystemService
(Context.LAYOUT_INFLATER_SERVICE);
When I create a class extends BaseAdapter, I get a warning message
Unconditional layout inflation from view adapter: Should use View Holder pattern (use recycled view passed into this method as the second parameter) for smoother scrolling
Do I need to change my code like this suggestion? All my code is running smoothly, it's just whether it is necessary to change the code to do updata code with the latest styles? Or just need to add #SuppressLint({ "ViewHolder", "InflateParams" }) ?
My adapter
public View getView(int position, View convertView, ViewGroup parent) {
View v = inflater.inflate(R.layout.list_item, null);
TextView merchant_type = (TextView) v.findViewById(R.id.merchant_type);
TextView merchant_name = (TextView) v.findViewById(R.id.merchant_name);
TextView merchant_location = (TextView) v.findViewById(R.id.merchant_location);
VoucherBean obj = (VoucherBean) getItem(position);
merchant_type.setText(obj.getMerchantType());
merchant_name.setText(obj.getMerchantName());
merchant_location.setText(obj.getMerchantLocation());
return v;
}
If you want to change my code as recommended above warning, like what my code later? Sorry if my question is too basic for a beginner
if you have more data in your list view then you should use recycling, because it improves scrolling and performance also. here is code look like if you use view holder in your adapter.
your ViewHolder looks like
public class ViewHolder {
public TextView merchant_type;
public TextView merchant_name;
public TextView merchant_location;
}
and your getView method
View vi = convertView;
ViewHolder holder;
if (convertView == null) {
vi = inflater.inflate(R.layout.list_item, null);
holder = new ViewHolder();
holder.merchant_type = (TextView) vi.findViewById(R.id.merchant_type);
holder.merchant_name = (TextView) vi.findViewById(R.id.merchant_name);
holder.merchant_location = (TextView) vi.findViewById(R.id.merchant_location);
vi.setTag(holder);
} else
holder = (ViewHolder) vi.getTag();
// now set your text view here like
holder.merchant_name.setText("Bla Bla Bla");
// return your view
return vi;
The View Holder pattern is meant to make your code easier to read and to maintain. If you look at the standard ViewHolder you'll see that its a class that basically does what you do in your getView:
private static class ExampleViewHolder{
TextView merchant_type;
TextView merchant_name;
TextView merchant_location;
public ExampleViewHolder(View view){
merchant_type = (TextView) v.findViewById(R.id.merchant_type);
merchant_name = (TextView) v.findViewById(R.id.merchant_name);
merchant_location = (TextView) v.findViewById(R.id.merchant_location);
}
}
Then in your getView method you'd get your view like this:
ExampleViewHolder holder = new ExampleViewHolder(view);
view.setTag(holder);
It's good to have them and the newer apis kind of force the use of this pattern, however as you can see by the code it doesn't change much besides readability and ease of maintenance.
However! There is an important part of the getView method that you are missing, and is most likely the reason for the warning.
The listview recycles the views, and gives them back to the adapter so that the same view doesnt have to be inflated everytime. Saves resources and a lot of memory, and you're not making use of this very important aspect of the listView.
You see, the way it recycles views is passing the old view, that you inflated before, back to the adapter through the convertView, so if the convertView is not null you can be sure its the inflated layout that you are using. So use that instead of inflating a new one:
View view = convertView;
ExampleViewHolder holder;
if(view == null){//means convertView is also null
view = inflater.inflate(yourlayout, parent, false);
holder = new ExampleViewHolder(view);
view.setTag(holder);
}else{
holder = (ExampleViewHolder) view.getTag();
}
I know that many similar questions have been posted on stackoverflow, so please don't think I haven't searched high and low. I think my problems simply comes from now completely understanding listViews and the lifecycles of list items. I have a list view that can contain two types of messages, outbound or inbound. Originally, my listView would use a different background color depending on the type of message (outbound vs inbound), and it worked flawlessly. Now my application doesn't require a different background for list items, but it actually requires different layouts for different list items.
This is a clip of my Adapter.
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
SoapBoxMessage thisMessage = messages.get(position);
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (thisMessage.isOutbound()) {
v = inflater.inflate(R.layout.outbound_row, null);
} else {
v = inflater.inflate(R.layout.inbound_row, null);
}
}
Adapters can support different ViewItemTypes that will solve your recycling problems.
static public enum LAYOUT_TYPE {
INBOUND,
OUTBOUND
}
#Override
public int getViewTypeCount () {
return LAYOUT_TYPE.values().length;
}
#Override
public int getItemViewType (int position) {
if ( messages.get(position).isOutbound())
return LAYOUT_TYPE.OUTBOUND.ordinal();
else
return LAYOUT_TYPE.INBOUND.ordinal();
}
#Override
public View getView (int position, View convertView, ViewGroup parent) {
LAYOUT_TYPE itemType = LAYOUT_TYPE.values()[getItemViewType(position)];
... (code until inflater )
switch (itemType){
case INBOUND:
convertview = /inflate & configure inbound layout
break;
case OUTBOUND:
convertview = /inflate & configure outbound layout
break;
}
you don't need to worry about recycling views because the listview will respect the ViewItemTypes for each position and it will only provide a convertview of the correct viewtype for that position
The problem is that listview is recycling the view so when you check if the view is null it wont pass that because the view is not null when it is recycled
you would need to inflate the view each time getView is called, basically removing if(v == null)
Try to use a ViewHolder like this:
ViewHolder holder;
public View getView(int position, View convertView, ViewGroup parent) {
convertView = null;
SoapBoxMessage thisMessage = messages.get(position);
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (thisMessage.isOutbound()) {
convertView = inflater.inflate(R.layout.outbound, null, false);
//specific to your outbound layout
holder = new ViewHolder();
holder.text= (TextView)convertView.findViewById(R.id.textview);
holder.group = (RadioGroup)convertView.findViewById(R.id.toggleGroup);
holder.toggle = (ToggleButton)convertView.findViewById(R.id.toggleButton);
} else {
convertView = inflater.inflate(R.layout.inbound, null, false);
//specific to your inbound layout
holder = new ViewHolder();
holder.text= (TextView)convertView.findViewById(R.id.textview);
holder.group = (RadioGroup)convertView.findViewById(R.id.toggleGroup);
holder.toggle = (ToggleButton)convertView.findViewById(R.id.toggleButton);
}
convertView.setTag(holder);
}
else{
holder = (ViewHolder) convertView.getTag();
}
//Here you can set the text or other code you want to implement
holder.text.setText("Whatever!");
return convertView;
}
static class ViewHolder {
//TODO put components you use like:
TextView text;
RadioGroup group;
ToggleButton toggle;
}
It's because of the recycling that is happening. You would need something along these lines:
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
SoapBoxMessage thisMessage = messages.get(position);
if (convertView == null) {
LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
convertView = mInflater.inflate(R.layout.listview_feedlog_item, null);
holder = new ViewHolder();
holder.txtTime = (TextView) convertView.findViewById(R.id.textTime);
holder.txtDate = (TextView) convertView.findViewById(R.id.textDate);
convertView.setTag(holder);
} else
holder = (ViewHolder) convertView.getTag();
// I don't know how your SoapBoxMessage is made up so here are two sample methods
holder.txtTime.setText(thisMessage.getTime());
holder.txtDate.setText(thisMessage.getDate());
return convertView;
}
/* private view holder class */
private class ViewHolder {
TextView txtTime;
TextView txtDate;
}
Also, remember to always reset or initiate a value in the getView method. Since a View can be recycled it might carry with it properties of its former life.
Whether this is a good practice or not, Removing if (v == null) will solve the problem.
Anyway, you will have to re-inflate the view.