android.view.InflateException:二进制XML文件行#15:错误类膨胀

时间:2012-01-13 09:04:49

标签: android xml class classnotfoundexception inflate-exception

我已经实现了一个扩展视图的新ImageLoaderView,如果我以编程方式设置xml,则代码可以正常工作。但由于这似乎很难,我试图让它在我的res布局文件夹中的xml工作,但我收到一个错误。以下是我的代码。

LoaderImageView:

package com.anon.android.test;

import java.io.IOException;
import java.net.MalformedURLException;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.os.Handler.Callback;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;

/**
 * Free for anyone to use, just say thanks and share :-)
 * @author Blundell
 *
 */
public class LoaderImageView extends LinearLayout{

    private static final int COMPLETE = 0;
    private static final int FAILED = 1;

    private Context mContext;
    private Drawable mDrawable;
    private ProgressBar mSpinner;
    private ImageView mImage;

    /**
     * This is used when creating the view in XML
     * To have an image load in XML use the tag 'image="http://developer.android.com/images/dialog_buttons.png"'
     * Replacing the url with your desired image
     * Once you have instantiated the XML view you can call
     * setImageDrawable(url) to change the image
     * @param context
     * @param attrSet
     */
    public LoaderImageView(final Context context, final AttributeSet attrSet) {
        super(context, attrSet);
        final String url = attrSet.getAttributeValue(null, "image");
        if(url != null){
            instantiate(context, url);
        } else {
            instantiate(context, null);
        }
    }

    /**
     * This is used when creating the view programatically
     * Once you have instantiated the view you can call
     * setImageDrawable(url) to change the image
     * @param context the Activity context
     * @param imageUrl the Image URL you wish to load
     */
    public LoaderImageView(final Context context, final String imageUrl) {
        super(context);
        instantiate(context, imageUrl);     
    }

    /**
     *  First time loading of the LoaderImageView
     *  Sets up the LayoutParams of the view, you can change these to
     *  get the required effects you want
     */
    private void instantiate(final Context context, final String imageUrl) {
        mContext = context;

        mImage = new ImageView(mContext);
        mImage.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

        mSpinner = new ProgressBar(mContext);
        mSpinner.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

        mSpinner.setIndeterminate(true);

        addView(mSpinner);
        addView(mImage);

        if(imageUrl != null){
            setImageDrawable(imageUrl);
        }
    }

    /**
     * Set's the view's drawable, this uses the internet to retrieve the image
     * don't forget to add the correct permissions to your manifest
     * @param imageUrl the url of the image you wish to load
     */
    public void setImageDrawable(final String imageUrl) {
        mDrawable = null;
        mSpinner.setVisibility(View.VISIBLE);
        mImage.setVisibility(View.GONE);
        new Thread(){
            public void run() {
                try {
                    mDrawable = getDrawableFromUrl(imageUrl);
                    imageLoadedHandler.sendEmptyMessage(COMPLETE);
                } catch (MalformedURLException e) {
                    imageLoadedHandler.sendEmptyMessage(FAILED);
                } catch (IOException e) {
                    imageLoadedHandler.sendEmptyMessage(FAILED);
                }
            };
        }.start();
    }

    /**
     * Callback that is received once the image has been downloaded
     */
    private final Handler imageLoadedHandler = new Handler(new Callback() {
        public boolean handleMessage(Message msg) {
            switch (msg.what) {
            case COMPLETE:
                mImage.setImageDrawable(mDrawable);
                mImage.setVisibility(View.VISIBLE);
                mSpinner.setVisibility(View.GONE);
                break;
            case FAILED:
            default:
                // Could change image here to a 'failed' image
                // otherwise will just keep on spinning
                break;
            }
            return true;
        }       
    });

    /**
     * Pass in an image url to get a drawable object
     * @return a drawable object
     * @throws IOException
     * @throws MalformedURLException
     */
    private static Drawable getDrawableFromUrl(final String url) throws IOException, MalformedURLException {
        return Drawable.createFromStream(((java.io.InputStream)new java.net.URL(url).getContent()), "name");
    }

}

这是我的xml:

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

    <Button
        android:id="@+id/button_weather9"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Back" />

    <com.anon.android.test.LoaderImageview
        android:id="@+id/weather_icon"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_gravity="center_horizontal"
        android:scaleType="fitXY"
        image="http://developer.android.com/images/dialog_buttons.png"
        />

</LinearLayout> 

这就是我所说的:(在我的ImageLoading活动中 )

LoaderImageView image = (LoaderImageView) findViewById(R.id.weather_icon);

但是我收到了这个错误:

01-13 09:16:45.516: E/AndroidRuntime(216): Uncaught handler: thread main exiting due to uncaught exception
01-13 09:16:45.526: E/AndroidRuntime(216): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.anon.android.test/com.anon.android.test.ImageLoading}: android.view.InflateException: Binary XML file line #15: Error inflating class com.anon.android.test.LoaderImageview
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2496)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.app.ActivityThread.access$2200(ActivityThread.java:119)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.os.Handler.dispatchMessage(Handler.java:99)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.os.Looper.loop(Looper.java:123)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.app.ActivityThread.main(ActivityThread.java:4363)
01-13 09:16:45.526: E/AndroidRuntime(216):  at java.lang.reflect.Method.invokeNative(Native Method)
01-13 09:16:45.526: E/AndroidRuntime(216):  at java.lang.reflect.Method.invoke(Method.java:521)
01-13 09:16:45.526: E/AndroidRuntime(216):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
01-13 09:16:45.526: E/AndroidRuntime(216):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
01-13 09:16:45.526: E/AndroidRuntime(216):  at dalvik.system.NativeStart.main(Native Method)
01-13 09:16:45.526: E/AndroidRuntime(216): Caused by: android.view.InflateException: Binary XML file line #15: Error inflating class com.anon.android.test.LoaderImageview
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:576)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.view.LayoutInflater.rInflate(LayoutInflater.java:618)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.view.LayoutInflater.inflate(LayoutInflater.java:407)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
01-13 09:16:45.526: E/AndroidRuntime(216):  at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.app.Activity.setContentView(Activity.java:1622)
01-13 09:16:45.526: E/AndroidRuntime(216):  at com.anon.android.test.ImageLoading.onCreate(ImageLoading.java:22)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
01-13 09:16:45.526: E/AndroidRuntime(216):  ... 11 more
01-13 09:16:45.526: E/AndroidRuntime(216): Caused by: java.lang.ClassNotFoundException: com.anon.android.test.LoaderImageview in loader dalvik.system.PathClassLoader@44e8cad8
01-13 09:16:45.526: E/AndroidRuntime(216):  at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:243)
01-13 09:16:45.526: E/AndroidRuntime(216):  at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
01-13 09:16:45.526: E/AndroidRuntime(216):  at java.lang.ClassLoader.loadClass(ClassLoader.java:532)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.view.LayoutInflater.createView(LayoutInflater.java:466)
01-13 09:16:45.526: E/AndroidRuntime(216):  at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:565)
01-13 09:16:45.526: E/AndroidRuntime(216):  ... 20 more

我认为让我错误的是我在xml中声明我的LoaderImageView的方式。你能救我吗?

2 个答案:

答案 0 :(得分:7)

您需要在布局的根元素中添加应用的package,如下所示:

<LinearLayout 
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res/com.anon.android.test"
   .../>

然后当您为自定义视图充气时,会传递自定义属性,如下所示:

 <com.anon.android.test.LoaderImageview
      ...
      app:image="http://developer....png"/>

此外,我想您已在styleable attributes内声明了resources

修改

要为styleable attribute创建View,请在项目的attrs.xml文件夹中创建一个res\values文件,内容应如下所示:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="LoaderImageView">
        <attr name="image" format="string"/>
        //other attributes..
    </declare-styleable>
</resources>

答案 1 :(得分:1)

所以,与这个问题相关但不是同一个案例:我遇到了同样的问题,adb logcat输出并没有帮助那么多。

在查看我的代码后,我意识到我正在编写布局&#39; 查看&#39;注意&#39; 查看&#39;。显然,如果Android si试图膨胀的元素不存在或者名称无效,那么它会在没有非常有用的错误输出的情况下崩溃。