i think that this can be done, but maybe im wrong (Im sure im wrong). I have this adapter that sometimes uses a List of Class1 and in other moments uses a list of Class2. So, can i do TWO differents constructors where un the first one i use List1 and in the other one i use the List2?
public class SpinnerAdapter extends BaseAdapter {
private List<String> listaDeTexto;
private Activity activity;
private LayoutInflater layoutInflater;
private List<MetodoDePago> listaMetodosDePago;
private List<Banco> listaDeBancos;
public SpinnerAdapter(List<String> listaDeTexto, Activity activity, List<MetodoDePago> listaMetodosDePago) {
this.listaDeTexto = listaDeTexto;
this.activity = activity;
this.layoutInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.listaMetodosDePago = listaMetodosDePago;
}
public SpinnerAdapter(List<String> listaDeTexto, Activity activity, List<Banco> listaDeBancos) {
this.listaDeTexto = listaDeTexto;
this.activity = activity;
this.layoutInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.listaDeBancos = listaDeBancos;
}
#Override
public int getCount() {
return listaDeTexto.size();
}
#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) {
View view = convertView;
if (convertView == null){
view = layoutInflater.inflate(R.layout.spinner_custom,null);
}
TextView textView = view.findViewById(R.id.textViewSpinner);
textView.setText(listaDeTexto.get(position));
ImageView imageView = view.findViewById(R.id.imgViewSpinner);
Glide.with(view)
.load(listaMetodosDePago.get(position).getThumbnail())
.into(imageView);
return view;
}
}
Due to type erasure in Java, you are basically declaring two constructors which look like, SpinnerAdapter(List l1, Activity a, List l2) { } to Java.
A simple solution would be to create one constructor and add a type argument. So, something like, SpinnerAdapter(List l1, Activity a, List l2, int type) { }.
You can then check the type value in the constructor and the getView(...) method to initialize your variables as needed.
Related
I want to use my class GlobalState in my HomePlayerAdapter. When I click on a Switch in my ListView they should save the ID from my player object in GlobalState. But when I click on a Switch my App crashed.
Here my GlobalState class:
public class GlobalState extends Application {
private ArrayList<Integer> selectedPlayer;
public ArrayList<Integer> getSelectedPlayer() {
return selectedPlayer;
}
public void addSelectedPlayer(int p) {
this.selectedPlayer.add(p);
}
public void removeSelectedPlayer(int p) {
this.selectedPlayer.remove(p);
}
}
Here my HomePlayerAdapter class:
public class HomePlayerAdapter extends BaseAdapter {
private Context context;
private ArrayList<Player> items;
private GlobalState globalState;
public HomePlayerAdapter(Context context, ArrayList<Player> items){
this.context = context;
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null){
convertView = LayoutInflater.from(context).inflate(R.layout.home_player_list_item, parent, false);
}
globalState = (GlobalState) context.getApplicationContext();
final Player currentItem = (Player) getItem(position);
TextView playerName = (TextView) convertView.findViewById(R.id.PlayerItemTextView);
SwitchMaterial deckSwitch = (SwitchMaterial) convertView.findViewById(R.id.PlayerItemSwitch);
playerName.setText(currentItem.getName());
deckSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
if (isChecked){
globalState.addSelectedPlayer(currentItem.getId());
}if (!isChecked){
globalState.removeSelectedPlayer(currentItem.getId());
}
});
return convertView;
}
public int getCount() {
return items.size();
}
#Override
public Object getItem(int position) {
return items.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
}
When I click on a Switch then they call: deckSwitch.setOnCheckedChangeListener and check if the swith is checked or not. When its checked it should save the ID from the selected player in the GlobalState class and when its not checked then it should delete the ID.
I don't know if you have done this somewhere else in your code, but the code snippet that you provided, the problem lies in the fact that you haven't actually created the 'selectedPlayer' Arraylist. It can be checked if you are getting the nullPointerException.
although, I would suggest, rather than creating a globalState class like this, Make a class That would hold context Independent information, and declare static member variables, and methods. So that you do not have to instantiate the class for using. Since you are going to use selectedPlayer as a global variable anyway, its better to make it static, to prevent duplicate instantiation.
As for the solution to your problem for this particular case, just doing
private ArrayList<Integer> selectedPlayer = new ArrayList<>();
should be enough.
I'm getting a variable data sent from activity to my adapter by using
sendData method, but every time when I try to access it in my getView method it resets to 0, please help. I've tried to debug code to check if the data from an activity is passing and it looks ok. I also created a getNumb method but still, the variable resets to 0. Here is my adapter code:
public class WorkoutListAdapterTwo extends BaseAdapter {
private int y;
public WorkoutListAdapterTwo() {
}
public int sendData(int x){
this.y = x;
return y;
}
public int getNumb(){
return this.y;
}
private static LayoutInflater mLayoutInflater = null;
public WorkoutListAdapterTwo(Activity ctx) {
this.mLayoutInflater = ctx.getLayoutInflater();
}
#Override
public int getCount() {
return WorkoutContentTwo.WORKOUTSTWO.size();
}
#Override
public Object getItem(int position) {
return WorkoutContentTwo.WORKOUTSTWO.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
int j = getNumb();
WorkoutTwo workout = (WorkoutTwo) getItem(j);
String [] arrOfStrings = workout.name.split(",");
if (convertView == null) {
convertView = mLayoutInflater.inflate(R.layout.adapter_workout_row, parent, false);
holder = new ViewHolder();
holder.id = (TextView) convertView.findViewById(R.id.workout_id);
holder.name = (TextView) convertView.findViewById(R.id.workout_name);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Set the content for the ListView row
//holder.id.setText(workout.id);
//holder.name.setText(arrOfStrings[i]);
holder.id.setText(Integer.toString(position+1));
holder.name.setText(workout.ArrList[position]);
// Set the color for the ListView row
holder.id.setBackgroundColor(workout.dark);
holder.name.setBackgroundColor(workout.light);
return convertView;
}
Here I'm adding the code where I'm calling my method:
public void onItemSelected(int position) {
// Start the detail activity for the selected workout ID.
Intent detailIntent = new Intent(this, WorkoutDetailActivityTwo.class);
detailIntent.putExtra(WorkoutDetailFragmentTwo.ARG_WORKOUT_POS, position);
WorkoutListAdapterTwo newAdd = new WorkoutListAdapterTwo();
newAdd.sendData(position);
newAdd.notifyDataSetChanged();
startActivity(detailIntent);
}
Are you notifying your adapter to update views after updating the value? If your sendData() is not called until after the adapter has done it's first draw, you will need to call notifyDataSetChanged() so that the adapter knows there are new values that should be used to update your views.
You have to make a interface or you can a use notifyDataSetChanged depends on the use if you are doing search operation then use the notifyDataSetChanged method but if you want to send some data then
Fragment or activity
public class ExampleFragment extends Fragment implements MyAdapter.SuccessResponse{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View contentView = inflater.inflate(R.layout.my_layout, container, false);
MyAdapter myAdapter = new MyAdapter(getActivity(), 0);
myAdapter.successResponse = this;
return contentView;
}
#Override
public void onSuccess() {
}
}
The adapter code
class MyAdapter extends ArrayAdapter{
SuccessResponse successResponse;
public MyAdapter(Context context, int resource) {
super(context, resource);
}
public interface SuccessResponse{
void onSuccess();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
//ur views
linearLayout.setOnClickListener(new View.OnClickListener{
#Override
public void onClick (View view){
if(successResponse!=null)
successResponse.onSuccess();
}
})
}
}
You can use any type of adapter i am use arrayadaper here.
I'm creating a ListView with a custom adapter.
In the customer adapter class, I'm passing a Context object to its super class and also passing a Context object to the MainActivity while creating the object for the Adapter class.
It shows the following error
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mylistpractice/com.mylistpractice.MainActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object android.content.Context.getSystemService(java.lang.String)' on a null object reference
Now I pass getApplicationContext() rather than the Context object while passing the argument from MainActivity and it doesn't show any error.
I am confused about the difference between passing a Context object and passing getApplicationContext().
But it's not showing any data in the ListView.
This is the Adapter class
public class Myadapter extends ArrayAdapter<Data> {
ArrayList<Data> arraydata;
Context context;
public Myadapter(ArrayList<Data> arraydata,Context context) {
super(context,R.layout.content,arraydata);
this.arraydata=arraydata;
this.context=context;
}
#Override
public int getCount() {
return 0;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Data data=getItem(position);
Viewholder viewholder;
View vi=convertView;
if(vi==null) {
viewholder=new Viewholder();
LayoutInflater inflater = LayoutInflater.from(getContext());
vi = inflater.inflate(R.layout.content, parent, false);
viewholder.name=(TextView)vi.findViewById(R.id.name);
viewholder.id=(TextView)vi.findViewById(R.id.id);
vi.setTag(viewholder);
} else {
viewholder=(Viewholder)vi.getTag();
}
viewholder.name.setText(data.getName());
viewholder.id.setText(data.getId());
return vi;
}
public class Viewholder {
TextView id;
TextView name;
}
}
this is my MainActivity
public class MainActivity extends AppCompatActivity {
ListView list;
ArrayList<Data> arraydata=new ArrayList<>();
Myadapter myadapter;
Context context;
Data data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list=(ListView)findViewById(R.id.list);
setList();
myadapter = new Myadapter(arraydata,MainActivity.this);
list.setAdapter(myadapter);
}
public void setList() {
for(int i=0;i<15;i++) {
String s,id;
data = new Data();
data.setName("Farhana:::"+i);
s = data.getName();
data.setId("Id:::"+i);
id = data.getId();
arraydata.add(data);
Log.e("DAtA:--",s);
Log.e("ID:--",id);
}
}
}
but not showing anydata in listview
Because you told it not to create any views.
#Override
public int getCount() {
return 0;
}
You are using an ArrayAdapter. You don't need to implement getCount, but if you do, return the size of the list
#Override
public int getCount() {
return arraydata == null ? 0 : arraydata.size();
}
Anyways, regarding your question, tend to use MainActivity.this like you have done for the Context (Activities are Contexts).
If your error is here
LayoutInflater inflater = LayoutInflater.from(getContext());
Then, that could instead be
LayoutInflater inflater = LayoutInflater.from(this.context);
which you got the context from the constructor
you are overriding method getCount(); and it is returning zero, you have to return the size of the array-list.
I'm reading in places that it's necessary to have a main method in each class like this:
public static void main(String args [ ]) { }
However, none of my classes in my current project contain such a method, and so far my app experiences no issues...here's one of my classes for reference.
public class GridAdapter extends BaseAdapter {
private final String[] classes = {"Database"}; // Sets the labels for each button
private Context mContext;
public GridAdapter(Context c) {
mContext = c;
}
public int getCount() { //autogenerated tab, returns length of an array.
return mThumbIds.length;
}
// The position an item is in in an array.
public Object getItem(int position) {
return mThumbIds[position];
}
// Gets the ID of each item in the array.
public long getItemId(int position) {
return 0;
}
// create a new ImageView for each item referenced by the Adapter
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View gridView;
if (convertView == null) { // if it's not recycled, initialize some attributes
gridView = new View(mContext);
gridView = inflater.inflate(R.layout.gridset, null);
TextView textView = (TextView) gridView
.findViewById(R.id.label);
textView.setText(classes[position]);
ImageView imageView = (ImageView) gridView
.findViewById(R.id.img);
imageView.setImageResource(mThumbIds[position]);
} else {
gridView = convertView;
}
return gridView;
}
// references to our images
private Integer[] mThumbIds = {
R.drawable.img};
}
Is it because I'm extending something (in this case BaseAdapter)? Right now the classes that are currently complete and actually function have an extension, So I am wondering if my WIP classes that don't will need a main() method.
Your reference reads "in at least one class" and pertains to a standalone Java SE program.
In Android you, however, do not need main at all. Your Activities will be brought to life by Android OS calling callbacks into your Activities such as onCreate, onPause etc...
I have created an application that can show call logs. I am using LazyAdapter class. I am showing an icon according to the call type: Missed / Incoming / Outgoing. This part is not working properly. The display of text like name, number, date and time is showing just fine except the Call type?
Here is what I am trying to do:
public class LazyAdapter extends BaseAdapter
{
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public LazyAdapter(Activity a, ArrayList<HashMap<String, String>> d)
{
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount()
{
return data.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;
if(convertView==null)
vi = inflater.inflate(R.layout.callist, null);
TextView name = (TextView)vi.findViewById(R.id.name);
TextView number = (TextView)vi.findViewById(R.id.phone_number);
TextView date = (TextView)vi.findViewById(R.id.date);
TextView time = (TextView)vi.findViewById(R.id.time);
TextView duration = (TextView)vi.findViewById(R.id.duration);
ImageView callType = (ImageView)vi.findViewById(R.id.calType);
ImageView clock = (ImageView)vi.findViewById(R.id.Clock);
HashMap<String, String> pro = new HashMap<String, String>();
pro = data.get(position);
if((pro.get(ListOfCall.contactName)!=null))
{
name.setText(pro.get(ListOfCall.contactName));
}
else
{
name.setText("Unknown");
}
number.setText(pro.get(ListOfCall.phone));
date.setText(pro.get(ListOfCall.DateOfCall));
time.setText(pro.get(ListOfCall.TimeOfCall));
String type = pro.get(ListOfCall.typeofCall);
if(type.equalsIgnoreCase("OUTGOING"))
{
callType.setImageResource(R.drawable.outgoing);
duration.setText(pro.get(ListOfCall.durationOfCall));
}
else if(type.equalsIgnoreCase("INCOMING"))
{
callType.setImageResource(R.drawable.incoming);
duration.setText(pro.get(ListOfCall.durationOfCall));
}
else if(type.equalsIgnoreCase("MISSED"))
{
callType.setImageResource(R.drawable.missed);
duration.setVisibility(4);
clock.setVisibility(4);
}
return vi;
}
}
I am not really sure where the problem is coming because I am able get correct results in the arraylist called data in the top. Things change when I move the arraylist to Hashmap called pro.
Again the values are coming up properly except the call type and it's corresponding images are not coming up.
Can somebody help me out to fix this up?
Figured out the conditions that were in LazyAdapter class didn't work as required. Removed the condition and added them in before class that was sending values to LazyAdapter class.
Works fine now!!
Thanks!