【问题标题】:Android App - Selecting Image from Phone Gallery and Adding it to a ListViewAndroid 应用程序 - 从手机图库中选择图像并将其添加到 ListView
【发布时间】:2016-04-30 07:40:21
【问题描述】:

我正在使用自定义适配器将选定的图像添加到 ListView。我收到此错误:

 04-29 18:15:33.582: E/AndroidRuntime(24214): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.ImageView.setImageBitmap(android.graphics.Bitmap)' on a null object reference
04-29 18:15:33.582: E/AndroidRuntime(24214):    at app.photoexpress.ViewAlbumActivity$ImageAdapter.getView(ViewAlbumActivity.java:240)

当从图库中添加照片时,我会创建一个新的照片对象并将给定的位图存储在其中。我的 getBitmap() 方法调用了它,但在这种情况下它显然是空的。不知道这里出了什么问题

这是我的代码:

public class ViewAlbumActivity extends AppCompatActivity {
    ListView listview;
    ImageAdapter adapter;
    CharSequence[] images;
    int width = 250;
    boolean isSearch = false;
    // ArrayList<String> listItems = new ArrayList<String>();
    TextView title;
    Album album;
    ArrayList<Album> albumList;
    String albumName = "Album";
    Album currentlySelectedAlbum;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_main);
        // get bundle
        Bundle bundle = getIntent().getExtras();
        if (bundle != null) {
            albumList = (ArrayList<Album>) bundle.getSerializable("albums");
            albumName = bundle.getString("albumName");
            album = Album.findAlbum(albumName, getBaseContext());
            Log.e(".", album.getName());
            setTitle(albumName);
        } else {
            album = new Album("placeholder");
        }

        currentlySelectedAlbum = Album.findAlbum(albumName, getBaseContext());
        ArrayList<Photo> photoList = currentlySelectedAlbum.getPhotos();

        // Displays the icon and album name in the action bar
        getSupportActionBar().setDisplayShowHomeEnabled(true);
        getSupportActionBar().setLogo(R.drawable.ic_launcher);
        getSupportActionBar().setDisplayUseLogoEnabled(true);

        listview = (ListView) findViewById(R.id.listView1);
        adapter = new ImageAdapter(this, photoList);

        listview.setAdapter(adapter);
        // images = readPhotoList();

        // Display display = this.getWindowManager().getDefaultDisplay();
        // width = display.getWidth();
        // width=width/2-15;

        /*listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

                Intent intent = new Intent(ViewAlbumActivity.this, ViewPhotoActivity.class);
                // intent.putExtra(name, value)
                intent.putExtra("index", position);
                intent.putExtra("albumname", albumName);
                intent.putExtra("album", album);
                intent.putExtra("isSearch", isSearch);
                startActivity(intent);
            }
        });*/
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        if (!isSearch) {
            getMenuInflater().inflate(R.menu.viewalbum, menu);

        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        if (!isSearch) {
            int id = item.getItemId();
            if (id == R.id.addPhoto) {
                Intent intent = new Intent(Intent.ACTION_PICK,
                        android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(intent, 1);

                // addPhoto();
                return true;
            }
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == RESULT_OK) {
            Uri targetUri = data.getData();
            // textTargetUri.setText(targetUri.toString());
            Bitmap bitmap;
            try {
                bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(targetUri));
                //image.setImageBitmap(bitmap);
                Photo photo = new Photo(bitmap);
                currentlySelectedAlbum.addPhoto(photo);
                Album.updateAlbumList(currentlySelectedAlbum, getBaseContext());
                adapter.notifyDataSetChanged();
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    /*
     * private String[] readPhotoList() { String path =
     * Environment.getExternalStorageDirectory().getAbsolutePath() + "/photos/";
     * 
     * File dir = new File(path);
     * 
     * File[] filelist = dir.listFiles();
     * 
     * if (filelist == null) { String[] z = new String[1]; z[0] = "no file in "
     * + path; return z; }
     * 
     * if (filelist.length == 0) { String[] s = new String[1]; s[0] =
     * "no image file under " + path; return s; } ArrayList<String> result = new
     * ArrayList<String>(); for (int i = 0; i < filelist.length; i++) { if
     * (BitmapFactory.decodeFile(path + filelist[i].getName()) != null) {
     * result.add(filelist[i].getName()); } } String[] convertList = new
     * String[result.size()]; for (int i = 0; i < result.size(); i++) {
     * convertList[i] = result.get(i); } return convertList;
     * 
     * }
     */

    /////////////

    class ImageAdapter extends BaseAdapter {
        private Context mContext;

        public ArrayList<Photo> photoList2;

        public ImageAdapter(Context c, ArrayList<Photo> photoList) {
            mContext = c;
            this.photoList2 = photoList;
        }

        public int getCount() {
            int returnInt = 0;
            try {
                returnInt = currentlySelectedAlbum.getPhotos().size();
            } catch (NullPointerException e) {
                Log.e("NullPointerError", ".");
            }
            return returnInt;
        }

        public Object getItem(int position) {
            return null;
        }

        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) {
            ImageView imageView = new ImageView(mContext);

            View vi = convertView;
            // String fileName="";
            if (convertView == null) {
                /*imageView = new ImageView(mContext);
                imageView.setLayoutParams(new ListView.LayoutParams(width, width));
                imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                imageView.setPadding(0, 0, 0, 0);*/
                LayoutInflater inflator = (LayoutInflater)ViewAlbumActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                vi  = inflator.inflate(R.layout.customimageview, parent, false);

            } /*else {
                imageView = (ImageView) convertView;
            }
            // if there is any photo
            if (album.getPhotos().size() != 0) {
                // final String fileName =
                // album.getPhotos().get(position).getName();
                // showImgFromSD("/photos/" + fileName, imageView);
                // showImgFromSD("/photos/002.jpg",imageView);
            }*/

            Bitmap bitmap = photoList2.get(position).getBitmap();
            ImageView thumbnail = (ImageView)vi.findViewById(R.id.imageView1);
            thumbnail.setImageBitmap(bitmap);
            return imageView;

        }

        /*
         * private void showImgFromSD(String fileName, ImageView iv) { File f =
         * new File(Environment.getExternalStorageDirectory(), fileName);
         * FileInputStream input = null;
         * 
         * try { input = new FileInputStream(f); } catch (FileNotFoundException
         * e) { // toastMsg("File: " + fileName + " not found"); return; }
         * Bitmap pic = BitmapFactory.decodeStream(input, null, null);
         * iv.setImageBitmap(pic);
         * 
         * }
         */
    }

    /*
     * private void addPhoto() { final CharSequence[] options = images;
     * AlertDialog.Builder build = new
     * AlertDialog.Builder(ViewAlbumActivity.this);
     * build.setTitle("../sdcard/photos/"); build.setItems(options, new
     * DialogInterface.OnClickListener() { public void onClick(DialogInterface
     * dialog, int item) { Album tempAlbum = findAlbum(albumName, albumList);
     * Album allPhotos = findAlbum("All Photos", albumList); List<Photo> Photos
     * = tempAlbum.getPhotos();
     * 
     * for (Photo p : Photos) { //if (p.getName().compareToIgnoreCase((String)
     * options[item]) == 0) { toastMsg(options[item] + " already in album");
     * return; } } //Photo tempPhoto = new Photo((String) options[item], "");
     * tempAlbum.addPhoto(tempPhoto); allPhotos.addPhoto(tempPhoto);
     * 
     * // SERIALIZE HERE
     * 
     * // listItems.add((String) options[item]); adapter.notifyDataSetChanged();
     * listview.invalidateViews(); toastMsg(options[item] + " added.");
     * 
     * } }); AlertDialog alert = build.create(); alert.show(); }
     */

    // handles pop up messages
    private void toastMsg(String msg) {
        Context context = getApplicationContext();
        CharSequence text = msg;
        int duration = Toast.LENGTH_LONG;
        Toast toast = Toast.makeText(context, text, duration);
        toast.show();
    }
}

专辑.java:

public class Album implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = -7593044560206879666L;
    String name;
    static ArrayList<Photo> photos;
    boolean previouslySelected = false;

    public Album() {
        photos = new ArrayList<Photo>();
    }

    public Album(String name) {
        this.name = name;
        photos = new ArrayList<Photo>();
    }

    public String toString() {
        return name;
    }

    public String getName() {
        return name;
    }

    public static ArrayList<Album> deleteAlbum(int position, Context context) {

        ArrayList<Album> albumList = new ArrayList<Album>();
        albumList = SerializableManager.readSerializable(context, "albumList.ser");

        albumList.remove(albumList.get(position));
        return albumList;

    }

    public static ArrayList<Album> addAlbum(Album a, Context context) {

        ArrayList<Album> albumList = new ArrayList<Album>();
        albumList = SerializableManager.readSerializable(context, "albumList.ser");

        for (Album i : albumList) {
            if (i.getName().equalsIgnoreCase(a.getName())) {
                Log.e("Not Added", "Album not added because it already exists.");
                CreateNewAlbumActivity.toastMsg("Not added. Album already exists.");
                return albumList;
            }
        }
        albumList.add(a);

        return albumList;

    }

    public static void updateAlbumList(Album a, Context context){

        ArrayList<Album> albumList = SerializableManager.readSerializable(context, "albumList.ser");

        for (int i = 0; i < albumList.size(); i++){
            if (albumList.get(i).getName().equals(a.getName())){
                albumList.remove(i);
                albumList.add(a);
            }
        }

        SerializableManager.saveSerializable(context, albumList, "albumList.ser");

    }

    public static boolean doesAlbumExist(String name, Context context) {

        ArrayList<Album> albumList = SerializableManager.readSerializable(context, "albumList.ser");
        for (Album i : albumList) {
            if (i.getName().equalsIgnoreCase(name)) {
                return true;
            }
        }

        return false;

    }

    public static Album findAlbum(String name, Context context) {

        ArrayList<Album> albumList = SerializableManager.readSerializable(context, "albumList.ser");
        for (Album i : albumList) {
            if (i.getName().equalsIgnoreCase(name)) {
                return i;
            }
        }

        return null;

    }

    public static ArrayList<Album> renameAlbum(String oldName, String newName, Context context) {

        ArrayList<Album> albumList = new ArrayList<Album>();
        albumList = SerializableManager.readSerializable(context, "albumList.ser");

        for (Album i : albumList) {
            if (i.getName().equalsIgnoreCase(oldName)) {
                Log.e(".", "match found");
                if (!doesAlbumExist(newName, context)) {
                    i.rename(newName);
                }
            }
        }

        return albumList;

    }

    public void rename(String newName) {
        this.name = newName;
    }

    public ArrayList<Photo> getPhotos() {
        return photos;
    }

    public void addPhoto(Photo p) {
        photos.add(p);
        return;
    }

}

Photo.java

public class Photo implements Serializable{

    // The Constant storeDir.
    public static final String storeDir = "data\\photo";
    int id;
    String Caption;
    Bitmap bitmap;
    List<Tag> Tags = new ArrayList <Tag>();

    public Photo(Bitmap bitmap) {
    id = 1 + (int)(Math.random() * 5000); 
    this.bitmap = bitmap;
    }

    public  Photo(String caption, Bitmap bitmap) {
        Caption = caption;
        id = 1 + (int)(Math.random() * 5000); 

        this.bitmap = bitmap;
    }


    public void setCaption(String input)
    {
        Caption = input;
    }

    public boolean hasTag( String type, String value)
    {
        for(Tag s: Tags )
        {
            if(s.Type.compareToIgnoreCase(type) == 0 && s.value.compareToIgnoreCase(value) == 0 )
            {
                return true;
            }
        }
        return false;
    }

    public boolean addTag( String type, String value)
    {

        //if tag already there error
        if(!hasTag(type,value))
        {
            Tags.add(new Tag(value,type));
            return true;
        }
        else
            return false;
    }

    public boolean deleteTag( String type, String value)
    {
        int count = 0;
        for(Tag s: Tags )
        {
            if(s.Type.compareToIgnoreCase(type) == 0 && s.value.compareToIgnoreCase(value) == 0 )
            {
                Tags.remove(count);
                return true;
            }
            count++;
        }
        return false;           
    }

    @Override
    public String toString()
    {
        return "no";
    }

    public List<Tag> getTags()
    {
        return Tags;
    }


    public String getCaption()
    {
        return Caption;
    }


    public Bitmap getBitmap(){
        return bitmap;
    }
    @Override
    public boolean equals(Object o)
    {
        if (o==null)
        {
            return false;
        }
        if(!(o instanceof Photo)) {return false;}
        Photo other = (Photo)o;
        return (true);

        //FIX THIS
    }
}

customimageview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

【问题讨论】:

    标签: android image listview android-imageview


    【解决方案1】:

    根据您的堆栈跟踪,您从它开始看起来错误发生在这一行(有点难不知道这实际上是第 240 行):

    thumbnail.setImageBitmap(位图);

    由于您的错误是 NullPointer,这意味着缩略图为空,这告诉我们:

    ImageView 缩略图 = (ImageView)vi.findViewById(R.id.imageView1);

    找不到 ImageView。因此,要到达根目录,我们需要查看以下 xml:

    R.layout.customimageview

    但那里似乎没有 ID 为 imageView1 的 imageView。如果没有添加一个应该解决空指针。 如果不是这种情况,并且那里有一个 ImageView,我们将继续调查。 :) (但同时也发布您的 xml,并请准确确认第 240 行是哪一行。)

    编辑:

    同时查看您的代码,您的适配器未完全实现,如果未修复,您稍后可能会遇到其他错误。例如方法 getItem 和 getItemId。

    getItem 应该看起来像这样:

      public Object getItem(int position) {
          return photolist2.get(position);
      }
    

    和getItemId:

    public long getItemId(int position) {
        return position;
    }
    

    编辑2:

    此外,虽然 Serializable 方便且容易,但它确实带来了一些负面影响,例如 Android 上的速度,查找 Parceble 并帮助您使用样板代码可能会很好:https://github.com/johncarl81/parceler。但那是以后的事了;)

    编辑 3:

    查看更多包含一些错误的适配器代码,这应该更接近您想要的:

    类 ImageAdapter 扩展 BaseAdapter { 私有上下文 mContext;

        public ArrayList<Photo> photoList2;
    
        public ImageAdapter(Context c, ArrayList<Photo> photoList) {
            mContext = c;
            this.photoList2 = photoList;
        }
    
        public int getCount() {
            int returnInt = 0;
            try {
                returnInt = currentlySelectedAlbum.getPhotos().size();
            } catch (NullPointerException e) {
                Log.e("NullPointerError", ".");
            }
            return returnInt;
        }
    
        public Object getItem(int position) {
            return photoList2.get(position);
        }
    
        public long getItemId(int position) {
            return position;
        }
    
        // create a new ImageView for each item referenced by the Adapter
        public View getView(int position, View convertView, ViewGroup parent) {
            View vi;
    
            // String fileName="";
            if (convertView == null) {
                /*imageView = new ImageView(mContext);
                imageView.setLayoutParams(new ListView.LayoutParams(width, width));
                imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
                imageView.setPadding(0, 0, 0, 0);*/
                LayoutInflater inflator = (LayoutInflater)ViewAlbumActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                vi  = inflator.inflate(R.layout.customimageview, parent, false);
    
            } else {
               vi = convertView;
            }
    
            Bitmap bitmap = photoList2.get(position).getBitmap();
            ImageView thumbnail = (ImageView)vi.findViewById(R.id.imageView1);
            thumbnail.setImageBitmap(bitmap);
            return vi;
        }
    

    那么有什么区别呢?在您的适配器中,您在顶部创建 ImageView 并在最后返回该视图。因此,当 Android 再次使用 convertView 调用 getView 时,convertView 现在持有该 ImageView 对象,而不是您创建的 customimageview 的视图。因此,当调用 vi.findViewByid 时,它试图在 ImageView 中查找 ImageView,因此失败了。

    【讨论】:

    • 我已经添加了xml。我确实有那个图像视图:/
    • 好的,你能把xml贴出来确认一下240是哪一行吗? :)
    • 我已经添加了,我可以确认第 240 行就是那一行
    • 嗯,似乎 if (convertView == null) 没有运行,因为如果我在该范围之外膨胀显示,错误就会消失。为什么会这样? @nerevar
    • 是的,我有点快,错过了一件事情。我使用更新的适配器为您编辑了答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    相关资源
    最近更新 更多