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.
Related
I am trying to send the context from my java class to my adapter of a RecyclerView, so I can click on the elements and be redirected to an intent. Apparently, the context isn't right. I've commented its line and the app works, but as soon as i try to prove it, it starts crashing again.
I assume its a context thing, but it would be pretty helpful if there's another way to set a click method to my elements.
The exception it throw its a null pointer exception:
java.lang.RuntimeException: Unable to start activity:
java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.widget.Button.setOnClickListener(android.view.View$OnClickListener)'
on a null object reference
Here is the adapter code:
public class SubsidioAdapter extends RecyclerView.Adapter<SubsidioAdapter.SubsidioViewHolder> {
private Context context;
private List<Producto> productoList;
private LayoutInflater inflater;
public SubsidioAdapter(Context context, List<Producto> productoList) {
this.context = context;
this.productoList = productoList;
this.inflater = LayoutInflater.from(context);
}
#Override
public SubsidioViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = this.inflater.inflate(R.layout.producto_item, null);
return new SubsidioViewHolder(view);
}
#Override
public void onBindViewHolder(SubsidioViewHolder subsidioViewHolder, int position) {
subsidioViewHolder.imageView.setImageResource(this.productoList.get(position).getFoto());
subsidioViewHolder.textView1.setText(this.productoList.get(position).getNombre());
subsidioViewHolder.textView2.setText(this.productoList.get(position).getDescripcion());
subsidioViewHolder.textView3.setText(this.productoList.get(position).getPrecio());
subsidioViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
context.startActivity(new
Intent(context, ModificarProductoActivity.class));
}
});
}
#Override
public int getItemCount() {
return this.productoList.size();
}
public class SubsidioViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
TextView textView1;
TextView textView2;
TextView textView3;
public SubsidioViewHolder(View itemView) {
super(itemView);
this.imageView = itemView.findViewById(R.id.fotoSub);
this.textView1 = itemView.findViewById(R.id.descSub);
this.textView2 = itemView.findViewById(R.id.nombreSub);
this.textView3 = itemView.findViewById(R.id.precioSub);
}
}
}
set an id to root element of adapter item layout, then find that view by id and use it instead of itemView ,
instead of :
subsidioViewHolder.itemView.setOnClickListener(new View.OnClickListener(){
public void onClick(View view) {
...
}
});
use:
subsidioViewHolder.rootLayout.setOnClickListener(new View.OnClickListener(){
public void onClick(View view) {
...
}
});
. and remember you can get context in recyclerView adapter inside onCreateViewHolder() without using constructor like this:
#Override
public SubsidioViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
context=viewGroup.getContext();
View view = this.inflater.inflate(R.layout.producto_item, null);
return new SubsidioViewHolder(view);
}
although it seems like that your problem is with
I am making a simple Android list view app which will show some basic name, in list view. My app is stopping unexpectedly. The logcat is showing this error.
Attempt to invoke virtual method 'android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()'
on a null object reference.
CustomAdapter
public class CustomAdapter extends BaseAdapter {
Context context;
String animals[];
LayoutInflater inflater;
public CustomAdapter(Context applicationContext, String[] animals){
this.context = applicationContext;
this.animals = animals;
inflater = (LayoutInflater.from(applicationContext));
}
#Override
public int getCount() {
return animals.length;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = inflater.inflate(R.layout.listview, null);
TextView textView = (TextView) view.findViewById(R.id.tv);
textView.setText(animals[i]);
return null;
}
}
Main Activity
public class MainActivity extends AppCompatActivity {
ListView listView;
String animals[]= {"Dog", "Cat", "Humans", "Monkey", "Rat", "Snake", "Elephant", "Giraffe", "Deer", "Tiger", "Lion","Cow", "Pig", "Goat"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView =(ListView) findViewById(R.id.lv);
CustomAdapter customAdapter = new CustomAdapter(getApplicationContext(), animals);
listView.setAdapter(customAdapter);
}
}
Here you did Mistakes
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = inflater.inflate(R.layout.listview, null);
TextView textView = (TextView) view.findViewById(R.id.tv);
textView.setText(animals[i]);
return view;
}
And
public long getItemId(int i) {
return animals.length;
}
Screenshort
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 have a fragment that displays a RecyclerView. I am currently handling the onclick event in my holder class like this:
public class CategoryHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public ImageView categoryImageView;
public TextView categoryNameTextView;
public TextView categoryAmountTextView;
ArrayList<Category> categoriesArrayList = new ArrayList<>();
Context context;
public CategoryHolder(View itemView, Context context, ArrayList<Category> categories) {
super(itemView);
this.categoriesArrayList = categories;
this.context = context;
itemView.setOnClickListener(this);
this.categoryImageView = (ImageView) itemView.findViewById(R.id.categoryImageView);
this.categoryNameTextView = (TextView) itemView.findViewById(R.id.categoryNameTextView);
this.categoryAmountTextView = (TextView) itemView.findViewById(R.id.categoryAmountTextView);
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
Category category = this.categoriesArrayList.get(position);
Toast.makeText(context, ""+category.getCategoryName() + position,
}
}
As you can see I have implemented OnClickListener in the holder class and then setTheOnItemClickListner in the Holder.
In my Adapter I pass the holder class the the arraylist with the data like this:
Context context;
ArrayList<Category> categories;
public CategoriesAdapter(Context context, ArrayList<Category> categories) {
this.context = context;
this.categories = categories;
}
#Override
public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.categorylist_singlecell, parent, false);
CategoryHolder holder = new CategoryHolder(v, context, categories);
return holder;
}
I am passing the data when creating the new holder.
This works fine and I can toast the position and any of the data from the ArrayList that is used for the RecyclerView.
What I want to do though is use that in the main fragment where I initialise the RecyclerView and adapter.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_nested_youtube_video_selection, container, false);
//////////////////////////// CATEGORIES RECYCLER /////////////////////////////////////
// Initialise the categories Recylerview
LinearLayoutManager categoriesLayoutManger = new LinearLayoutManager(getActivity());
categoriesLayoutManger.setOrientation(LinearLayoutManager.HORIZONTAL);
categoriesRecyclerView = (RecyclerView) view.findViewById(R.id.youtubeAlarmCategoryRecyclerView);
categoriesRecyclerView.setLayoutManager(categoriesLayoutManger);
// Get the data for the categories RecyclerView
categoryArraylist = CategoryCollection.getCategoryArrayList();
// Initialse the categories RecyclerView Adapter
categoriesAdapter = new CategoriesAdapter(getActivity(), categoryArraylist);
// Bind the categories Adapter to the categories RecyclerView
categoriesRecyclerView.setAdapter(categoriesAdapter);
I am thinking I need an interface but I am not sure how to do that or if that is even the best way to do it.
Following should work:
create an interface
create an instance of this interface in your fragment and pass it on to the adapter
let the adapter pass this interface on to the view holder
let the view holder define an onClickListener that passes the event on to the interface
Here's an example:
Interface
public interface ItemClickListener {
void onItemClicked(ViewHolder vh, Object item, int pos);
}
public interface GenericItemClickListener<T, VH extends ViewHolder> {
void onItemClicked(VH vh, T item, int pos);
}
ViewHolder
public class CategoryHolder extends RecyclerView.ViewHolder {
public CategoryHolder(View itemView, Context context) {
super(itemView);
this.context = context;
this.categoryImageView = (ImageView) itemView.findViewById(R.id.categoryImageView);
this.categoryNameTextView = (TextView) itemView.findViewById(R.id.categoryNameTextView);
this.categoryAmountTextView = (TextView) itemView.findViewById(R.id.categoryAmountTextView);
}
}
Adapter
Context context;
ArrayList<Category> categories;
ItemClickListener itemClickListener;
public CategoriesAdapter(Context context, ArrayList<Category> categories, ItemClickListener itemClickListener) {
this.context = context;
this.categories = categories;
this.itemClickListener = itemClickListener;
}
// DON'T PASS YOUR DATA HERE, just create a ViewHolder
#Override
public CategoryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.categorylist_singlecell, parent, false);
CategoryHolder holder = new CategoryHolder(v, context);
return holder;
}
//HERE you bind one item of your list to the view holder
#Override
public void onBindViewHolder(final CategoryHolder vh, final int i) {
final Category category = categories.get(i);
// set click listener
vh.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
itemClickListener.onItemClicked(vh, category, i);
}
});
// update images and texts...
}
Edit
Updated the code to show you, that you should not pass a array of items to every view holder... The view holder gets created and reused, only update the view holder in onBindViewHolder and bind the view holder instance to the correct data there...
Btw, I would make a generic interface instead, that's even more beautiful... My example is just a simple solution...
Edt 2 - How to create the interface instance
ItemClickListener listener = new ItemClickListener(){
#Override
public void onItemClicked(RecyclerView.ViewHolder vh, Object item, int pos){
Toast.makeText(getActivity(), "Item clicked: " + pos, Toast.LENGTH_SHORT).show();
}
};
abstract YOURAdapter class then add method like
void onLikeClicked(Object object, int position);
void onItemClicked();
call it in bindView as simply like
holder.btnLike.setOnclickListner(new OnClickListner){
onLikeClicked(list.get(position), position);
}
In Activity Class
now it will automatically implements all methods of adapter
YOURAdapter adapter=new YOURAdapter(){
void onLikeClicked(Object object, int position){
}
void onItemClicked(){
}
}
Been researching around this for a while and can't seem to find any solutions.
I have a 5 images that is in a PagerLayout swipe format.
What I want to do is upon clicking an image, I want to go to another XML file/class.
Code: (I've commented out methods I have tried.)
public class CustomSwipeAdapter extends PagerAdapter {
Context context;
private int[] image_resources = {R.drawable.chestpress,R.drawable.deadlift,R.drawable.squat,R.drawable.pullups,R.drawable.dips};
private Context ctx; //Gets the context of a current state or application. Tells program what is going on somewhere else.
private LayoutInflater layoutInflater; //USed to instantiate layout XML files to View Objct.
private LayoutInflater inflater;
private String[] names = {"Dumbell Press","Deadlift","Squats","Pullups","Tricep Dips"};
public ImageView imageView;
Activity activity;
View views = null;
public CustomSwipeAdapter(Context ctx){
this.ctx = ctx;
}
#Override
public int getCount() {
return image_resources.length;
}
#Override
public boolean isViewFromObject(View view, Object o) {
return view==(LinearLayout)o;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInflater = (LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View item_view = layoutInflater.inflate(R.layout.swipe_layout,container,false);
imageView = (ImageView)item_view.findViewById(R.id.image_view);
TextView textView = (TextView)item_view.findViewById(R.id.image_count);
imageView.setImageResource(image_resources[position]);
textView.setText(names[position]);
container.addView(item_view);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(position == 0) {
Log.d("Exercise","Dumbell Press");
//Intent intent = new Intent(ctx,MyActivity.class);
//Intent intent = new Intent(CustomSwipeAdapter.this,MyActivity.class);
//Intent intent = new Intent(context,MyActivity.class);
//views = inflater.inflate(R.layout.main,null);
//context.startActivity(intent);
//MyActivity koo = new MyActivity(); (Tried just instantiating another class (Im so lost)
}
if(position == 1){
Log.d("Exercise","Deadlift!");
}
if(position == 2){
Log.d("Exercise","Squats");
}
}
});
return item_view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((LinearLayout)object);
}
}
Very new android/java programmer. Thanks for reading.
Try this:
Intent intent = new Intent(CustomSwipeAdapter.this.ctx, MyActivity.class);
CustomSwipeAdapter.this.ctx.startActivity(intent);
Also make sure to pass the correct context to your Adapter constructor. The context you will pass can be the activity itself.
So, on your Activity, when you need to create a new adapter, do it like:
CustomSwipeAdapter myAdapter = new CustomSwipeAdapter(this);
Where this is the Activity on which you are creating the adapter.
If you need to create the adapter inside a fragment, just get the activity with:
MyFragment.getActivity();
Lastly, if you are wondering: "why does that work? It expects a Context and I'm passing an activity!".
Here's a short answer:
Activity inherits context. Thus, if you are in an activity, you only
need to pass itself to use the context. It also contains a pointer to
getBaseContext(). You might occasionally need to reference that, if
you need the entire application context, but most likely you won't for
a while.
Hope this helps.
Let me know if you get any more errors (don't forget to post your logcat so we can help you better).
What you should ideally be doing is this,
1: Create an interface call it swipeAdapterCallback or something, declare a method for handling the onClick
2: Make sure you get the swipeAdapterCallback instance in the constructor.
3: Then all you have to do is invoke the onClick method in the callback instance.
I've posted the adapter code here:
public class CustomSwipeAdapter extends PagerAdapter {
Context context;
private int[] image_resources = {R.drawable.chestpress, R.drawable.deadlift, R.drawable.squat, R.drawable.pullups, R.drawable.dips};
private Context ctx; //Gets the context of a current state or application. Tells program what is going on somewhere else.
private LayoutInflater layoutInflater; //USed to instantiate layout XML files to View Objct.
private LayoutInflater inflater;
private String[] names = {"Dumbell Press", "Deadlift", "Squats", "Pullups", "Tricep Dips"};
public ImageView imageView;
Activity activity;
View views = null;
private swipeAdapterCallback mCallback;
public CustomSwipeAdapter(Context ctx,swipeAdapterCallback callback) {
this.ctx = ctx;
this.mCallback = callback;
}
#Override
public int getCount() {
return image_resources.length;
}
#Override
public boolean isViewFromObject(View view, Object o) {
return view == (LinearLayout) o;
}
#Override
public Object instantiateItem(ViewGroup container, final int position) {
inflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
layoutInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View item_view = layoutInflater.inflate(R.layout.swipe_layout, container, false);
imageView = (ImageView) item_view.findViewById(R.id.image_view);
TextView textView = (TextView) item_view.findViewById(R.id.image_count);
imageView.setImageResource(image_resources[position]);
textView.setText(names[position]);
container.addView(item_view);
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mCallback.onImageClick(position);
}
});
return item_view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((LinearLayout) object);
}
public interface swipeAdapterCallback {
void onImageClick(int position);
}
}
Then in your activity what you do is implement this interface and handle the onClick in the onImageClick function like so
#Override
public void onImageClick(int position) {
//handle intents and launching activities here.
switch(position){
case 0:
Log.d("Exercise","Dumbell Press");
Intent intent = new Intent(this,exampleAcitivity.class);
startActivity(intent);
break;
case 1:
Log.d("Exercise","Deadlift!");
break;
case 3:
Log.d("Exercise","Squats");
break;
}
}
Since this block of code will be inside your Activity class creating intents and starting new activities handling result from these actitivities become very simple