Reputation: 253
I have a baseadapter for a gridView that creates a view when there is none. Here is the getView section:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Try to reuse the views
ImageView view = (ImageView) convertView;
boolean checked = (mCheckBox==null)?false:(((CheckBox) mCheckBox).isChecked());
// if convert view is null then create a new instance else reuse it
if (view == null) {
view = new ImageView(Context);
Log.d("GridViewAdapter", "new imageView added");
view.setId(R.id.iconImageView_id);
}
if(checked == true){
isSdReadable();
Log.i("GridViewAdapter", "checkbox is checked");
} else {
Log.i("GridView", "Icons not for use/checkbox not checked");
}
view.setImageResource(drawables.get(position));
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
view.setLayoutParams(new android.widget.GridView.LayoutParams(70, 70));
view.setTag(String.valueOf(position));
return view;
}
as you can see, I gave the view the new id iconImageView_id
based on this xml layout file in my values section:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="iconImageView_id"/>
</resources>
I am trying to use that imageView in another class so that I can assign a bitmap to it like this:
// Load back the image file to confirms it works
Bitmap bitmap = BitmapFactory.decodeFile( file.getAbsolutePath() );
ImageView imageView1 = (ImageView)v.findViewById(R.id.iconImageView_id);
imageView1.setImageBitmap( bitmap );
Log.i("AppInfoAdapter", "The icon image has been set into the gridView");
}
but the other class also is a baseadapter.
Here is the full section of the class where I am trying to use the imageView:
Log.d("AppInfoAdapter", "Data Set To Display");
addCheckbox
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (addCheckbox.isChecked()) {
System.out.println("Checked");
PackageManager pm = mContext.getPackageManager();
final int DEST_IMAGE_WIDTH = 100;
final int DEST_IMAGE_HEIGHT = 100;
ApplicationInfo appInfo = mContext.getApplicationInfo();
Drawable appIcon = pm.getApplicationIcon(appInfo);
Bitmap appBmp = Bitmap.createBitmap(DEST_IMAGE_WIDTH, DEST_IMAGE_HEIGHT, Config.ARGB_8888);
// Creates a new canvas based on the image specification
// created just above.
Canvas canvas = new Canvas(appBmp);
// (optional) Fills the entire canvas
canvas.drawColor(Color.WHITE);
// You need to set bounds otherwise a 0,0 sized image would be drawn.
appIcon.setBounds(0, 0, DEST_IMAGE_WIDTH, DEST_IMAGE_HEIGHT);
appIcon.draw(canvas);
/// Let's save to a .jpg file ...
File file = new File(mContext.getFilesDir().getAbsolutePath() + "/test2.jpg");
FileOutputStream out;
try
{
file.createNewFile();
out = new FileOutputStream(file);
appBmp.compress(Bitmap.CompressFormat.JPEG, 80, out);
Log.i("AppInfoAdapter", "The icon for use in gridView is saved");
out.close();
// Load back the image file to confirms it works
Bitmap bitmap = BitmapFactory.decodeFile( file.getAbsolutePath() );
ImageView imageView1 = (ImageView)v.findViewById(R.id.iconImageView_id);
imageView1.setImageBitmap( bitmap );
Log.i("AppInfoAdapter", "The icon image has been set into the gridView");
}
catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
catch (IOException e2)
{
e2.printStackTrace();
}
} else {
System.out.println("Un-Checked");
}
}
});
// return view
return v;
}
So I get a NPE because I apparently can't just statically reference the view.
So how can I make it so that I can use that imageView in my other class?
Here is the stacktrace error:
FATAL EXCEPTION: main
12-22 15:58:45.782: E/AndroidRuntime(28793): java.lang.NullPointerException
12-22 15:58:45.782: E/AndroidRuntime(28793): at com.example.awesomefilebuilderwidget.AppInfoAdapter$1.onClick(AppInfoAdapter.java:200)
12-22 15:58:45.782: E/AndroidRuntime(28793): at android.view.View.performClick(View.java:2532)
12-22 15:58:45.782: E/AndroidRuntime(28793): at android.widget.CompoundButton.performClick(CompoundButton.java:99)
12-22 15:58:45.782: E/AndroidRuntime(28793): at android.view.View$PerformClick.run(View.java:9308)
12-22 15:58:45.782: E/AndroidRuntime(28793): at android.os.Handler.handleCallback(Handler.java:587)
12-22 15:58:45.782: E/AndroidRuntime(28793): at android.os.Handler.dispatchMessage (Handler.java:92)
12-22 15:58:45.782: E/AndroidRuntime(28793): at android.os.Looper.loop(Looper.java:150)
12-22 15:58:45.782: E/AndroidRuntime(28793): at android.app.ActivityThread.main(ActivityThread.java:4333)
12-22 15:58:45.782: E/AndroidRuntime(28793): at java.lang.reflect.Method.invokeNative(Native Method)
12-22 15:58:45.782: E/AndroidRuntime(28793): at java.lang.reflect.Method.invoke(Method.java:507)
12-22 15:58:45.782: E/AndroidRuntime(28793): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
12-22 15:58:45.782: E/AndroidRuntime(28793): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
12-22 15:58:45.782: E/AndroidRuntime(28793): at dalvik.system.NativeStart.main(Native Method)
with line 200 being:
imageView1.setImageBitmap( bitmap );
ADDED:
Here are the two full classes that I am dealing with:
AppInfoAdapter.java:
package com.example.awesomefilebuilderwidget;
IMPORTS
public class AppInfoAdapter extends BaseAdapter implements Filterable {
private Context mContext;
private List<ResolveInfo> mListAppInfo;
private PackageManager mPackManager;
private List<ResolveInfo> originalListAppInfo;
private Filter filter;
private String fname;
public AppInfoAdapter(Context c, List<ResolveInfo> listApp,
PackageManager pm) {
mContext = c;
this.originalListAppInfo = this.mListAppInfo = listApp;
mPackManager = pm;
Log.d("AppInfoAdapter", "top");
}
@Override
public int getCount() {
Log.d("AppInfoAdapter", "getCount()");
return mListAppInfo.size();
}
@Override
public Object getItem(int position) {
Log.d("AppInfoAdapter", "getItem");
return mListAppInfo.get(position);
}
@Override
public long getItemId(int position) {
Log.d("AppInfoAdapter", "getItemId");
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
// get the selected entry
final ResolveInfo entry = (ResolveInfo) mListAppInfo.get(position);
// reference to convertView
View v = convertView;
// inflate new layout if null
if (v == null) {
LayoutInflater inflater = LayoutInflater.from(mContext);
v = inflater.inflate(R.layout.layout_appinfo, null);
Log.d("AppInfoAdapter", "New layout inflated");
}
// load controls from layout resources
ImageView ivAppIcon = (ImageView) v.findViewById(R.id.ivIcon);
TextView tvAppName = (TextView) v.findViewById(R.id.tvName);
TextView tvPkgName = (TextView) v.findViewById(R.id.tvPack);
final CheckBox addCheckbox = (CheckBox) v
.findViewById(R.id.addCheckbox);
Log.d("AppInfoAdapter", "Controls from layout Resources Loaded");
// set data to display
ivAppIcon.setImageDrawable(entry.loadIcon(mPackManager));
tvAppName.setText(entry.activityInfo.loadLabel(mPackManager));
tvPkgName.setText(entry.activityInfo.packageName);
Log.d("AppInfoAdapter", "Data Set To Display");
addCheckbox
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (addCheckbox.isChecked()) {
System.out.println("Checked");
PackageManager pm = mContext.getPackageManager();
final int DEST_IMAGE_WIDTH = 100;
final int DEST_IMAGE_HEIGHT = 100;
ApplicationInfo appInfo = mContext.getApplicationInfo();
Drawable appIcon = pm.getApplicationIcon(appInfo);
Bitmap appBmp = Bitmap.createBitmap(DEST_IMAGE_WIDTH, DEST_IMAGE_HEIGHT, Config.ARGB_8888);
// Creates a new canvas based on the image specification
// created just above.
Canvas canvas = new Canvas(appBmp);
// (optional) Fills the entire canvas
canvas.drawColor(Color.WHITE);
// You need to set bounds otherwise a 0,0 sized image would be drawn.
appIcon.setBounds(0, 0, DEST_IMAGE_WIDTH, DEST_IMAGE_HEIGHT);
appIcon.draw(canvas);
/// Let's save to a .jpg file ...
File file = new File(mContext.getFilesDir().getAbsolutePath() + "/test2.jpg");
FileOutputStream out;
try
{
file.createNewFile();
out = new FileOutputStream(file);
appBmp.compress(Bitmap.CompressFormat.JPEG, 80, out);
Log.i("AppInfoAdapter", "The icon for use in gridView is saved");
out.close();
// Load back the image file to confirms it works
Bitmap bitmap = BitmapFactory.decodeFile( file.getAbsolutePath() );
ImageView imageView1 = (ImageView)v.findViewById(R.id.iconImageView_id);
imageView1.setImageBitmap( bitmap );
Log.i("AppInfoAdapter", "The icon image has been set into the gridView");
}
catch (FileNotFoundException e1)
{
e1.printStackTrace();
}
catch (IOException e2)
{
e2.printStackTrace();
}
} else {
System.out.println("Un-Checked");
}
}
});
// return view
return v;
}
and GridViewAdapter.java:
package com.example.awesomefilebuilderwidget;
IMPORTS
public class GridViewAdapter extends BaseAdapter {
private Context Context;
// Keep all Images in array list
public ArrayList<Integer> drawables = new ArrayList<Integer>();
CheckBox mCheckBox=null;
// Constructor
public GridViewAdapter(Context c){
Context = c;
Log.d("GridViewAdapter", "Constructor is set");
drawables.add(R.drawable.pattern1);
Log.d("GridViewAdapter", "pattern1 added");
drawables.add(R.drawable.pattern2);
Log.d("GridViewAdapter", "pattern2 added");
drawables.add(R.drawable.trashcan);
Log.d("GridViewAdapter", "trashcan added");
drawables.add(R.drawable.ic_launcher);
Log.d("GridViewAdapter", "ic_launcher added");
}
public void setCheckBox(CheckBox checkbox){
mCheckBox=checkbox;
}
@Override
// How many items are in the data set represented by this Adapter
public int getCount() {
return drawables.size();
}
@Override
// Get the data item associated with the specified position in the
// data set
public Object getItem(int position) {
return drawables.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
public boolean isSdReadable() {
boolean mExternalStorageAvailable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = true;
Log.i("isSdReadable", "External storage card is readable.");
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
Log.i("isSdReadable", "External storage card is readable.");
mExternalStorageAvailable = true;
} else {
// Something else is wrong. It may be one of many other
// states, but all we need to know is we can neither read nor write
mExternalStorageAvailable = false;
}
return mExternalStorageAvailable;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Try to reuse the views
ImageView view = (ImageView) convertView;
boolean checked = (mCheckBox==null)?false:(((CheckBox) mCheckBox).isChecked());
// if convert view is null then create a new instance else reuse it
if (view == null) {
view = new ImageView(Context);
Log.d("GridViewAdapter", "new imageView added");
view.setId(R.id.iconImageView_id);
}
if(checked == true){
isSdReadable();
Log.i("GridViewAdapter", "checkbox is checked");
} else {
Log.i("GridView", "Icons not for use/checkbox not checked");
}
view.setImageResource(drawables.get(position));
view.setScaleType(ImageView.ScaleType.CENTER_CROP);
view.setLayoutParams(new android.widget.GridView.LayoutParams(70, 70));
view.setTag(String.valueOf(position));
return view;
}
}
Upvotes: 0
Views: 2774
Reputation: 2886
How are you trying the two adapaters together? Just loking at this you're probably getting that NPE because the view heirachies that the two adapters point to are not the same. (I.E they each generate their own views, and the views which are passed in do not correlate across adapters).
If you really want to do this the way you are, then you may be find success by doing the following:
Define a root layout, root.xml.
In your MainActivity constructor, infalte this view like so:
ViewGroup viewRoot = LayoutInfalter.from(this).inflate(R.layout.xml);
setContentView(viewRoot);
maintain the reference to viewRoot throughout the application, and any views you add should use this parent view (or views within this parent view) to host their views.
When you do the call:
ImageView imageView1 = (ImageView)v.findViewById(R.id.iconImageView_id);
Instead of using the passed in view (which I suspect is coming from either a pralell section of the view heiarchy which doesn't contain your view (thus the NPE)) use this:
viewRoot.findViewById(R.id.iconImageView_id);
As long as your ordering is correct (I.E. the view exists at the point this is called) you should now have access.
Upvotes: 1