二进制 XML 文件行 #75:膨胀 class 时出错

Binary XML file line #75: Error inflating class

我正在按照 http://www.androidhive.info/2014/06/android-facebook-like-custom-listview-feed-using-volley/ 中的教程创建一个类似 newsfeed 的 facebook。但是我收到以下错误,我无法理解。 感谢任何帮助。

我的logcat如下

FATAL EXCEPTION: main
android.view.InflateException: Binary XML file line #75: Error inflating class info.androidhive.listviewfeed.FeedImageView
                                                                     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:698)
                                                                     at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
                                                                     at android.view.LayoutInflater.rInflate(LayoutInflater.java:749)
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
                                                                     at example.com.samplemad.adapter.FeedListAdapter.getView(FeedListAdapter.java:61)
                                                                     at android.widget.AbsListView.obtainView(AbsListView.java:2267)
                                                                     at android.widget.ListView.measureHeightOfChildren(ListView.java:1244)
                                                                     at android.widget.ListView.onMeasure(ListView.java:1156)
                                                                     at android.view.View.measure(View.java:15172)
                                                                     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
                                                                     at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1390)
                                                                     at android.widget.LinearLayout.measureVertical(LinearLayout.java:681)
                                                                     at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
                                                                     at android.view.View.measure(View.java:15172)
                                                                     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
                                                                     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
                                                                     at android.view.View.measure(View.java:15172)
                                                                     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
                                                                     at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1390)
                                                                     at android.widget.LinearLayout.measureVertical(LinearLayout.java:681)
                                                                     at android.widget.LinearLayout.onMeasure(LinearLayout.java:574)
                                                                     at android.view.View.measure(View.java:15172)
                                                                     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814)
                                                                     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310)
                                                                     at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2148)
                                                                     at android.view.View.measure(View.java:15172)
                                                                     at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1848)
                                                                     at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1100)
                                                                     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1273)
                                                                     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998)
                                                                     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4212)
                                                                     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
                                                                     at android.view.Choreographer.doCallbacks(Choreographer.java:555)
                                                                     at android.view.Choreographer.doFrame(Choreographer.java:525)
                                                                     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
                                                                     at android.os.Handler.handleCallback(Handler.java:615)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:92)
                                                                     at android.os.Looper.loop(Looper.java:137)
                                                                     at android.app.ActivityThread.main(ActivityThread.java:4745)
                                                                     at java.lang.reflect.Method.invokeNative(Native Method)
                                                                     at java.lang.reflect.Method.invoke(Method.java:511)
                                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
                                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
                                                                     at dalvik.system.NativeStart.main(Native Method)
                                                                  Caused by: java.lang.ClassNotFoundException: info.androidhive.listviewfeed.FeedImageView
                                                                     at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
                                                                     at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
                                                                     at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
                                                                     at android.view.LayoutInflater.createView(LayoutInflater.java:552)
                                                                     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:687)
                                                                     at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) 
                                                                     at android.view.LayoutInflater.rInflate(LayoutInflater.java:749) 
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 
                                                                     at android.view.LayoutInflater.inflate(LayoutInflater.java:352) 
                                                                     at example.com.samplemad.adapter.FeedListAdapter.getView(FeedListAdapter.java:61) 
                                                                     at android.widget.AbsListView.obtainView(AbsListView.java:2267) 
                                                                     at android.widget.ListView.measureHeightOfChildren(ListView.java:1244) 
                                                                     at android.widget.ListView.onMeasure(ListView.java:1156) 
                                                                     at android.view.View.measure(View.java:15172) 
                                                                     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814) 
                                                                     at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1390) 
                                                                     at android.widget.LinearLayout.measureVertical(LinearLayout.java:681) 
                                                                     at android.widget.LinearLayout.onMeasure(LinearLayout.java:574) 
                                                                     at android.view.View.measure(View.java:15172) 
                                                                     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814) 
                                                                     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 
                                                                     at android.view.View.measure(View.java:15172) 
                                                                     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814) 
                                                                     at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1390) 
                                                                     at android.widget.LinearLayout.measureVertical(LinearLayout.java:681) 
                                                                     at android.widget.LinearLayout.onMeasure(LinearLayout.java:574) 
                                                                     at android.view.View.measure(View.java:15172) 
                                                                     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4814) 
                                                                     at android.widget.FrameLayout.onMeasure(FrameLayout.java:310) 
                                                                     at com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure(PhoneWindow.java:2148) 
                                                                     at android.view.View.measure(View.java:15172) 
                                                                     at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:1848) 
                                                                     at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1100) 
                                                                     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1273) 
                                                                     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998) 
                                                                     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4212) 
                                                                     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725) 
                                                                     at android.view.Choreographer.doCallbacks(Choreographer.java:555) 
                                                                     at android.view.Choreographer.doFrame(Choreographer.java:525) 
                                                                     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711) 
                                                                     at android.os.Handler.handleCallback(Handler.java:615) 
                                                                     at android.os.Handler.dispatchMessage(Handler.java:92) 
                                                                     at android.os.Looper.loop(Looper.java:137) 

以下是我的适配器 class。

public class FeedListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<FeedItem> feedItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();

public FeedListAdapter(Activity activity, List<FeedItem> feedItems) {
    this.activity = activity;
    this.feedItems = feedItems;
}

@Override
public int getCount() {
    return feedItems.size();
}

@Override
public Object getItem(int location) {
    return feedItems.get(location);
}

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if (inflater == null)
        inflater = (LayoutInflater) activity
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    if (convertView == null)
        convertView = inflater.inflate(R.layout.feed_item, null);

    if (imageLoader == null)
        imageLoader = AppController.getInstance().getImageLoader();

    TextView name = (TextView) convertView.findViewById(R.id.name);
    TextView timestamp = (TextView) convertView
            .findViewById(R.id.timestamp);
    TextView statusMsg = (TextView) convertView
            .findViewById(R.id.txtStatusMsg);
    TextView url = (TextView) convertView.findViewById(R.id.txtUrl);
    NetworkImageView profilePic = (NetworkImageView) convertView
            .findViewById(R.id.profilePic);
    FeedImageView feedImageView = (FeedImageView) convertView
            .findViewById(R.id.feedImage1);

    FeedItem item = feedItems.get(position);

    name.setText(item.getName());

    // Converting timestamp into x ago format
    CharSequence timeAgo = DateUtils.getRelativeTimeSpanString(
            Long.parseLong(item.getTimeStamp()),
            System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS);
    timestamp.setText(timeAgo);

    // Chcek for empty status message
    if (!TextUtils.isEmpty(item.getStatus())) {
        statusMsg.setText(item.getStatus());
        statusMsg.setVisibility(View.VISIBLE);
    } else {
        // status is empty, remove from view
        statusMsg.setVisibility(View.GONE);
    }

    // Checking for null feed url
    if (item.getUrl() != null) {
        url.setText(Html.fromHtml("<a href=\"" + item.getUrl() + "\">"
                + item.getUrl() + "</a> "));

        // Making url clickable
        url.setMovementMethod(LinkMovementMethod.getInstance());
        url.setVisibility(View.VISIBLE);
    } else {
        // url is null, remove from the view
        url.setVisibility(View.GONE);
    }

    // user profile pic
    profilePic.setImageUrl(item.getProfilePic(), imageLoader);

    // Feed image
    if (item.getImge() != null) {
        feedImageView.setImageUrl(item.getImge(), imageLoader);
        feedImageView.setVisibility(View.VISIBLE);
        feedImageView
                .setResponseObserver(new FeedImageView.ResponseObserver() {
                    @Override
                    public void onError() {
                    }

                    @Override
                    public void onSuccess() {
                    }
                });
    } else {
        feedImageView.setVisibility(View.GONE);
    }

    return convertView;
  }

}

这是我的 FeedImageView.java class

public class FeedImageView extends ImageView {

public interface ResponseObserver {
    public void onError();

    public void onSuccess();
}

private ResponseObserver mObserver;

public void setResponseObserver(ResponseObserver observer) {
    mObserver = observer;
}

/**
 * The URL of the network image to load
 */
private String mUrl;

/**
 * Resource ID of the image to be used as a placeholder until the network
 * image is loaded.
 */
private int mDefaultImageId;

/**
 * Resource ID of the image to be used if the network response fails.
 */
private int mErrorImageId;

/**
 * Local copy of the ImageLoader.
 */
private ImageLoader mImageLoader;

/**
 * Current ImageContainer. (either in-flight or finished)
 */
private ImageLoader.ImageContainer mImageContainer;

public FeedImageView(Context context) {
    this(context, null);
}

public FeedImageView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public FeedImageView(Context context, AttributeSet attrs,
                     int defStyle) {
    super(context, attrs, defStyle);
}

/**
 * Sets URL of the image that should be loaded into this view. Note that
 * calling this will immediately either set the cached image (if available)
 * or the default image specified by
 * {@link //VolleyImageView#setDefaultImageResId(int)} on the view.
 *
 * NOTE: If applicable, {@link //VolleyImageView#setDefaultImageResId(int)}
 * and {@link //VolleyImageView#setErrorImageResId(int)} should be called
 * prior to calling this function.
 *
 * @param url
 *            The URL that should be loaded into this ImageView.
 * @param imageLoader
 *            ImageLoader that will be used to make the request.
 */
public void setImageUrl(String url, ImageLoader imageLoader) {
    mUrl = url;
    mImageLoader = imageLoader;
    // The URL has potentially changed. See if we need to load it.
    loadImageIfNecessary(false);
}

/**
 * Sets the default image resource ID to be used for this view until the
 * attempt to load it completes.
 */
public void setDefaultImageResId(int defaultImage) {
    mDefaultImageId = defaultImage;
}

/**
 * Sets the error image resource ID to be used for this view in the event
 * that the image requested fails to load.
 */
public void setErrorImageResId(int errorImage) {
    mErrorImageId = errorImage;
}

/**
 * Loads the image for the view if it isn't already loaded.
 *
 * @param isInLayoutPass
 *            True if this was invoked from a layout pass, false otherwise.
 */
private void loadImageIfNecessary(final boolean isInLayoutPass) {
    final int width = getWidth();
    int height = getHeight();

    boolean isFullyWrapContent = getLayoutParams() != null
            && getLayoutParams().height == LinearLayout.LayoutParams.WRAP_CONTENT
            && getLayoutParams().width == LinearLayout.LayoutParams.WRAP_CONTENT;
    // if the view's bounds aren't known yet, and this is not a
    // wrap-content/wrap-content
    // view, hold off on loading the image.
    if (width == 0 && height == 0 && !isFullyWrapContent) {
        return;
    }

    // if the URL to be loaded in this view is empty, cancel any old
    // requests and clear the
    // currently loaded image.
    if (TextUtils.isEmpty(mUrl)) {
        if (mImageContainer != null) {
            mImageContainer.cancelRequest();
            mImageContainer = null;
        }
        setDefaultImageOrNull();
        return;
    }

    // if there was an old request in this view, check if it needs to be
    // canceled.
    if (mImageContainer != null && mImageContainer.getRequestUrl() != null) {
        if (mImageContainer.getRequestUrl().equals(mUrl)) {
            // if the request is from the same URL, return.
            return;
        } else {
            // if there is a pre-existing request, cancel it if it's
            // fetching a different URL.
            mImageContainer.cancelRequest();
            setDefaultImageOrNull();
        }
    }

    // The pre-existing content of this view didn't match the current URL.
    // Load the new image
    // from the network.
    ImageLoader.ImageContainer newContainer = mImageLoader.get(mUrl,
            new ImageLoader.ImageListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    if (mErrorImageId != 0) {
                        setImageResource(mErrorImageId);
                    }

                    if (mObserver != null) {
                        mObserver.onError();
                    }
                }

                @Override
                public void onResponse(final ImageLoader.ImageContainer response,
                                       boolean isImmediate) {
                    // If this was an immediate response that was delivered
                    // inside of a layout
                    // pass do not set the image immediately as it will
                    // trigger a requestLayout
                    // inside of a layout. Instead, defer setting the image
                    // by posting back to
                    // the main thread.
                    if (isImmediate && isInLayoutPass) {
                        post(new Runnable() {
                            @Override
                            public void run() {
                                onResponse(response, false);
                            }
                        });
                        return;
                    }

                    int bWidth = 0, bHeight = 0;
                    if (response.getBitmap() != null) {

                        setImageBitmap(response.getBitmap());
                        bWidth = response.getBitmap().getWidth();
                        bHeight = response.getBitmap().getHeight();
                        adjustImageAspect(bWidth, bHeight);

                    } else if (mDefaultImageId != 0) {
                        setImageResource(mDefaultImageId);
                    }

                    if (mObserver != null) {
                        mObserver.onSuccess();

                    }
                }
            });

    // update the ImageContainer to be the new bitmap container.
    mImageContainer = newContainer;

}

private void setDefaultImageOrNull() {
    if (mDefaultImageId != 0) {
        setImageResource(mDefaultImageId);
    } else {
        setImageBitmap(null);
    }
}

@Override
protected void onLayout(boolean changed, int left, int top, int right,
                        int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    loadImageIfNecessary(true);
}

@Override
protected void onDetachedFromWindow() {
    if (mImageContainer != null) {
        // If the view was bound to an image request, cancel it and clear
        // out the image from the view.
        mImageContainer.cancelRequest();
        setImageBitmap(null);
        // also clear out the container so we can reload the image if
        // necessary.
        mImageContainer = null;
    }
    super.onDetachedFromWindow();
}

@Override
protected void drawableStateChanged() {
    super.drawableStateChanged();
    invalidate();
}

/*
 * Adjusting imageview height
 * */
private void adjustImageAspect(int bWidth, int bHeight) {
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) getLayoutParams();

    if (bWidth == 0 || bHeight == 0)
        return;

    int swidth = getWidth();
    int new_height = 0;
    new_height = swidth * bHeight / bWidth;
    params.width = swidth;
    params.height = new_height;
    setLayoutParams(params);
  }

}                                                     

将您 XML 第 75 行中的包名称从 info.androidhive.listviewfeed.FeedImageView 更改为 您的 packagename.FeedImageView 试试这个,告诉我是否可以帮助你解决这个错误