Android - 从网络下载图片,保存到应用程序私有的内部存储位置,并在列表项中显示

6
我想要做的是:让我的应用程序从互联网上下载一张图片并将其保存到手机的内部存储器中,保存位置对应该应用程序。如果列表项中没有可用的图像(例如在互联网上找不到),我希望显示一个默认的占位符图像。这个默认图像是我在list_item_row.xml文件中定义的。
在我的ListActivity文件中,我调用了我编写的CustomCursorAdapter类的一个实例。在CustomCursorAdapter中,我遍历所有列表项,并定义需要映射到视图的内容,包括通过尝试从内部存储器中读取它来读取图像文件。
我看到了几个与此主题相关的问题,但这些示例要么特定于外部手机存储器(例如SD卡),要么涉及保存字符串而不是图像,或涉及使用Bitmap.CompressFormat来减少文件的分辨率(在我的情况下是不必要的,因为这些图像将是已经很小的缩略图)。尝试从每个示例中拼凑代码很困难,因此我询问我的具体示例。
目前,我相信我已经编写了有效的代码,但是我的列表项没有显示任何图像,包括默认的占位符图像。我不知道问题是由无效的下载/保存代码还是无效的读取代码引起的 - 我不知道如何检查内部存储器以查看图像是否存在。
无论如何,这是我的代码。非常感谢您的帮助。
ProductUtils.java
public static String productLookup(String productID, Context c) throws IOException {
    URL url = new URL("http://www.samplewebsite.com/" + productID + ".jpg");
    URLConnection connection = url.openConnection();
    InputStream input = connection.getInputStream();
    FileOutputStream output = 
        c.openFileOutput(productID + "-thumbnail.jpg", Context.MODE_PRIVATE);
    byte[] data = new byte[1024];

    output.write(data);
    output.flush();
    output.close();
    input.close();
}

CustomCursorAdapter.java

public class CustomCursorAdapter extends CursorAdapter {
    public CustomCursorAdapter(Context context, Cursor c) {
        super(context, c);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        ImageView thumbnail = (ImageView) view.findViewById(R.id.thumbnail);

        String fileName = 
                cursor.getString(cursor.getColumnIndex(DbAdapter.KEY_IMAGE_FILE_PATH));

        Bitmap bMap = BitmapFactory.decodeFile(fileName);
        thumbnail.setImageBitmap(bMap);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(context);
        View v = inflater.inflate(R.layout.list_item_row, parent, false);
        bindView(v, context, cursor);
        return v;
    }
}
3个回答

6

看起来有些代码被遗漏了,我重新写成了这样:

ProductUtils.java

public static String productLookup(String productID, Context c) throws IOException {

    URL url = new URL("http://www.samplewebsite.com/" + productID + ".jpg");

    InputStream input = null;
    FileOutputStream output = null;

    try {
        String outputName = productID + "-thumbnail.jpg";

        input = url.openConnection().getInputStream();
        output = c.openFileOutput(outputName, Context.MODE_PRIVATE);

        int read;
        byte[] data = new byte[1024];
        while ((read = input.read(data)) != -1)
            output.write(data, 0, read);

        return outputName;

    } finally {
        if (output != null)
            output.close();
        if (input != null)
            input.close();
    }
}

该应用程序无法使用该代码进行编译。它指出输入和输出变量需要初始化。我已经更正了有问题的行,将其改为“InputStream input = null”和“FileOutputStream output = null”,但是仍然存在同样的问题,没有图像显示。 - Keeb13r
看起来我得到的错误是这个:“java.io.IOException: 是一个目录”。我不确定该怎么想,因为我认为仅仅指定文件名而没有引入任何中间文件夹将导致写和读路径完全相同。 - Keeb13r
不行,它只能包含数字,有时候会用X代表10。我是否没有从正确的位置读取文件,即当我调用decodeFile()时,需要告诉它该文件所在的路径? - Keeb13r
有一件事我忘了问 - 下载图像代码块中是否需要任何catch语句?如果URL无法打开连接怎么办?如果没有输入流可供检索怎么办?难道不需要catch语句吗? - Keeb13r
如果“productLookup”抛出异常,您需要确定应该发生什么……也许使用默认图像? - dacwe
显示剩余5条评论

2

看起来只是在尝试读取图像文件名称时不够,我必须调用getFilesDir()获得文件存储路径。以下是我使用的代码:

String path = context.getFilesDir().toString();
String fileName = cursor.getString(cursor.getColumnIndex(DbAdapter.KEY_PRODUCT_ID));

if (fileName != null && !fileName.equals("")) {
    Bitmap bMap = BitmapFactory.decodeFile(path + "/" + fileName);
    if (bMap != null) {
        thumbnail.setImageBitmap(bMap);
    }
}

那么我的问题是有效的:“写入日志,以确保您已经写入并读取了相同的文件?” - dacwe
最初,我并不知道除了文件名之外还需要其他信息,我认为应用程序自己知道文件所在的具体路径。 - Keeb13r

-1
void  writeToFile(Bitmap _bitmapScaled)
    {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        _bitmapScaled.compress(Bitmap.CompressFormat.PNG, 40, bytes);
        try{
        File f;
        //you can create a new file name "test.jpg" in sdcard folder.
        if (android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED))
            f =new File(android.os.Environment.getExternalStorageDirectory(),"FamilyLocator/userimages/"+imageName);
        else
         f = new File(Environment.getDataDirectory(),"FamilyLocator/userimages/"+imageName);

        f.createNewFile();
        //write the bytes in file
        FileOutputStream fo = new FileOutputStream(f);
        fo.write(bytes.toByteArray());
        // remember close de FileOutput
        fo.close();
        }catch(Exception e){e.printStackTrace();}
    }

这段代码与问题实际无关,甚至无法编译。然而,我认为概述保留位图算法在未来有价值。 - IcedDante

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接