FORCE CLOSE:无法实例化片段确保类名存在,是公共的,并且有一个公共的空构造函数

时间:2013-11-21 15:03:03

标签: java android

ERROR:

Unable to instantiate fragment com.examples.youtubeapidemo.VideoListDemoActivity$VideoListFragment: make sure class name exists, is public, and has an empty constructor that is public

我的源代码中没有看到VideoListDemoActivity的任何引用。我相信这种情况发生的原因是我从以下版本复制了这个类:

https://code.google.com/p/youtube-api-samples/source/browse/android-player/src/com/examples/youtubeapidemo/VideoListDemoActivity.java?r=b9d9565b17705d71a9c0093d8623c6b0c912e6d9

...我已将其重命名为MainActivity(旧名称为VideoListDemoActivity)但所有对VideoListDemoActivity的引用都已消失,因此我不知道为什么会抛出这个关于VideoListDemoActivity的错误。

logcat的:

11-21 09:52:28.461: E/AndroidRuntime(31054): FATAL EXCEPTION: main
11-21 09:52:28.461: E/AndroidRuntime(31054): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.idg.omv/com.idg.omv.MainActivity}: android.view.InflateException: Binary XML file line #22: Error inflating class fragment
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2110)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2135)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.ActivityThread.access$700(ActivityThread.java:143)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1241)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.os.Handler.dispatchMessage(Handler.java:99)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.os.Looper.loop(Looper.java:137)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.ActivityThread.main(ActivityThread.java:4950)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at java.lang.reflect.Method.invokeNative(Native Method)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at java.lang.reflect.Method.invoke(Method.java:511)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1004)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:771)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at dalvik.system.NativeStart.main(Native Method)
11-21 09:52:28.461: E/AndroidRuntime(31054): Caused by: android.view.InflateException: Binary XML file line #22: Error inflating class fragment
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.view.LayoutInflater.inflate(LayoutInflater.java:459)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:309)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.Activity.setContentView(Activity.java:1914)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at com.idg.omv.MainActivity.onCreate(MainActivity.java:65)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.Activity.performCreate(Activity.java:5179)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2074)
11-21 09:52:28.461: E/AndroidRuntime(31054):    ... 11 more
11-21 09:52:28.461: E/AndroidRuntime(31054): Caused by: android.app.Fragment$InstantiationException: Unable to instantiate fragment com.examples.youtubeapidemo.VideoListDemoActivity$VideoListFragment: make sure class name exists, is public, and has an empty constructor that is public
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.Fragment.instantiate(Fragment.java:584)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.Fragment.instantiate(Fragment.java:552)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.Activity.onCreateView(Activity.java:4822)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:680)
11-21 09:52:28.461: E/AndroidRuntime(31054):    ... 21 more
11-21 09:52:28.461: E/AndroidRuntime(31054): Caused by: java.lang.ClassNotFoundException: com.examples.youtubeapidemo.VideoListDemoActivity$VideoListFragment
11-21 09:52:28.461: E/AndroidRuntime(31054):    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
11-21 09:52:28.461: E/AndroidRuntime(31054):    at android.app.Fragment.instantiate(Fragment.java:574)
11-21 09:52:28.461: E/AndroidRuntime(31054):    ... 24 more

XML#1:

<?xml version="1.0" encoding="utf-8"?>
<!--
  Copyright 2012 Google Inc. All Rights Reserved.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

  <fragment
      class="com.idg.omv.MainActivity$VideoListFragment"
      android:id="@+id/list_fragment"
      android:layout_width="match_parent"
      android:layout_height="match_parent"/>

  <LinearLayout
      android:id="@+id/video_box"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_gravity="bottom"
      android:orientation="vertical">

    <ImageButton
        android:id="@+id/close_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:src="@android:drawable/btn_dialog"
        android:onClick="onClickClose"/>

    <fragment
        class="com.idg.omv.MainActivity$VideoListFragment"
        android:id="@+id/video_fragment_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

  </LinearLayout>

</merge>

XML#2:

<?xml version="1.0" encoding="utf-8"?>
<!--
  Copyright 2012 Google Inc. All Rights Reserved.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="95dp"
    android:orientation="horizontal"
    android:gravity="center"
    android:background="?android:attr/activatedBackgroundIndicator">

  <com.google.android.youtube.player.YouTubeThumbnailView
      android:id="@+id/thumbnail"
      android:layout_width="wrap_content"
      android:layout_height="match_parent"
      android:src="@drawable/no_thumbnail"
      android:adjustViewBounds="true"
      android:scaleType="centerInside"/>

  <TextView
      android:id="@+id/text"
      android:layout_width="0dp"
      android:layout_height="wrap_content"
      android:layout_weight="1"
      android:layout_gravity="center_vertical"
      android:layout_marginLeft="5dp"
      android:textAppearance="?android:attr/textAppearanceSmall"
      android:textColor="#fff"/>

</LinearLayout>

当前的本地来源:

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;

import com.google.android.youtube.player.YouTubeInitializationResult;
import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayer.OnFullscreenListener;
import com.google.android.youtube.player.YouTubePlayer.OnInitializedListener;
import com.google.android.youtube.player.YouTubePlayer.Provider;
import com.google.android.youtube.player.YouTubePlayerFragment;
import com.google.android.youtube.player.YouTubeThumbnailLoader;
import com.google.android.youtube.player.YouTubeThumbnailLoader.ErrorReason;
import com.google.android.youtube.player.YouTubeThumbnailView;

import android.annotation.TargetApi;
import android.app.Activity;
import android.app.ListFragment;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * A sample Activity showing how to manage multiple YouTubeThumbnailViews in an adapter for display
 * in a List. When the list items are clicked, the video is played by using a YouTubePlayerFragment.
 * <p>
 * The demo supports custom fullscreen and transitioning between portrait and landscape without
 * rebuffering.
 */
@TargetApi(13)
public final class MainActivity extends Activity implements OnFullscreenListener {

  /** The duration of the animation sliding up the video in portrait. */
  private static final int ANIMATION_DURATION_MILLIS = 300;
  /** The padding between the video list and the video in landscape orientation. */
  private static final int LANDSCAPE_VIDEO_PADDING_DP = 5;

  private VideoListFragment listFragment;
  private VideoFragment videoFragment;

  private View videoBox;
  private View closeButton;

  private boolean isFullscreen;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.video_list_demo);

    listFragment = (VideoListFragment) getFragmentManager().findFragmentById(R.id.list_fragment);
    videoFragment =
        (VideoFragment) getFragmentManager().findFragmentById(R.id.video_fragment_container);

    videoBox = findViewById(R.id.video_box);
    closeButton = findViewById(R.id.close_button);

    videoBox.setVisibility(View.INVISIBLE);

    layout();
  }

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    layout();
  }

  @Override
  public void onFullscreen(boolean isFullscreen) {
    this.isFullscreen = isFullscreen;

    layout();
  }

  /**
   * Sets up the layout programatically for the three different states. Portrait, landscape or
   * fullscreen+landscape. This has to be done programmatically because we handle the orientation
   * changes ourselves in order to get fluent fullscreen transitions, so the xml layout resources
   * do not get reloaded.
   */
  private void layout() {
    boolean isPortrait =
        getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;

    listFragment.getView().setVisibility(isFullscreen ? View.GONE : View.VISIBLE);
    listFragment.setLabelVisibility(isPortrait);
    closeButton.setVisibility(isPortrait ? View.VISIBLE : View.GONE);

    if (isFullscreen) {
      videoBox.setTranslationY(0); // Reset any translation that was applied in portrait.
      setLayoutSize(videoFragment.getView(), MATCH_PARENT, MATCH_PARENT);
      setLayoutSizeAndGravity(videoBox, MATCH_PARENT, MATCH_PARENT, Gravity.TOP | Gravity.LEFT);
    } else if (isPortrait) {
      setLayoutSize(listFragment.getView(), MATCH_PARENT, MATCH_PARENT);
      setLayoutSize(videoFragment.getView(), MATCH_PARENT, WRAP_CONTENT);
      setLayoutSizeAndGravity(videoBox, MATCH_PARENT, WRAP_CONTENT, Gravity.BOTTOM);
    } else {
      videoBox.setTranslationY(0); // Reset any translation that was applied in portrait.
      int screenWidth = dpToPx(getResources().getConfiguration().screenWidthDp);
      setLayoutSize(listFragment.getView(), screenWidth / 4, MATCH_PARENT);
      int videoWidth = screenWidth - screenWidth / 4 - dpToPx(LANDSCAPE_VIDEO_PADDING_DP);
      setLayoutSize(videoFragment.getView(), videoWidth, WRAP_CONTENT);
      setLayoutSizeAndGravity(videoBox, videoWidth, WRAP_CONTENT,
          Gravity.RIGHT | Gravity.CENTER_VERTICAL);
    }
  }

  public void onClickClose(@SuppressWarnings("unused") View view) {
    listFragment.getListView().clearChoices();
    listFragment.getListView().requestLayout();
    videoFragment.pause();
    videoBox.animate()
        .translationYBy(videoBox.getHeight())
        .setDuration(ANIMATION_DURATION_MILLIS)
        .withEndAction(new Runnable() {
          @Override
          public void run() {
            videoBox.setVisibility(View.INVISIBLE);
          }
        });
  }

  /**
   * A fragment that shows a static list of videos.
   */
  public static final class VideoListFragment extends ListFragment {

    private static final List<VideoEntry> VIDEO_LIST;
    static {
      List<VideoEntry> list = new ArrayList<VideoEntry>();
      list.add(new VideoEntry("YouTube Collection", "Y_UmWdcTrrc"));
      list.add(new VideoEntry("GMail Tap", "1KhZKNZO8mQ"));
      list.add(new VideoEntry("Chrome Multitask", "UiLSiqyDf4Y"));
      list.add(new VideoEntry("Google Fiber", "re0VRK6ouwI"));
      list.add(new VideoEntry("Autocompleter", "blB_X38YSxQ"));
      list.add(new VideoEntry("GMail Motion", "Bu927_ul_X0"));
      list.add(new VideoEntry("Translate for Animals", "3I24bSteJpw"));
      VIDEO_LIST = Collections.unmodifiableList(list);
    }

    private PageAdapter adapter;
    private View videoBox;

    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      adapter = new PageAdapter(getActivity(), VIDEO_LIST);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
      super.onActivityCreated(savedInstanceState);

      videoBox = getActivity().findViewById(R.id.video_box);
      getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
      setListAdapter(adapter);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
      String videoId = VIDEO_LIST.get(position).videoId;

      VideoFragment videoFragment =
          (VideoFragment) getFragmentManager().findFragmentById(R.id.video_fragment_container);
      videoFragment.setVideoId(videoId);

      // The videoBox is INVISIBLE if no video was previously selected, so we need to show it now.
      if (videoBox.getVisibility() != View.VISIBLE) {
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
          // Initially translate off the screen so that it can be animated in from below.
          videoBox.setTranslationY(videoBox.getHeight());
        }
        videoBox.setVisibility(View.VISIBLE);
      }

      // If the fragment is off the screen, we animate it in.
      if (videoBox.getTranslationY() > 0) {
        videoBox.animate().translationY(0).setDuration(ANIMATION_DURATION_MILLIS);
      }
    }

    @Override
    public void onDestroyView() {
      super.onDestroyView();

      adapter.releaseLoaders();
    }

    public void setLabelVisibility(boolean visible) {
      adapter.setLabelVisibility(visible);
    }

  }

  /**
   * Adapter for the video list. Manages a set of YouTubeThumbnailViews, including initializing each
   * of them only once and keeping track of the loader of each one. When the ListFragment gets
   * destroyed it releases all the loaders.
   */
  private static final class PageAdapter extends BaseAdapter {

    private final List<VideoEntry> entries;
    private final List<View> entryViews;
    private final Map<YouTubeThumbnailView, YouTubeThumbnailLoader> thumbnailViewToLoaderMap;
    private final LayoutInflater inflater;
    private final ThumbnailListener thumbnailListener;

    private boolean labelsVisible;

    public PageAdapter(Context context, List<VideoEntry> entries) {
      this.entries = entries;

      entryViews = new ArrayList<View>();
      thumbnailViewToLoaderMap = new HashMap<YouTubeThumbnailView, YouTubeThumbnailLoader>();
      inflater = LayoutInflater.from(context);
      thumbnailListener = new ThumbnailListener();

      labelsVisible = true;
    }

    public void releaseLoaders() {
      for (YouTubeThumbnailLoader loader : thumbnailViewToLoaderMap.values()) {
        loader.release();
      }
    }

    public void setLabelVisibility(boolean visible) {
      labelsVisible = visible;
      for (View view : entryViews) {
        view.findViewById(R.id.text).setVisibility(visible ? View.VISIBLE : View.GONE);
      }
    }

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

    @Override
    public VideoEntry getItem(int position) {
      return entries.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
      View view = convertView;
      VideoEntry entry = entries.get(position);

      // There are three cases here
      if (view == null) {
        // 1) The view has not yet been created - we need to initialize the YouTubeThumbnailView.
        view = inflater.inflate(R.layout.video_list_item, parent, false);
        YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
        thumbnail.setTag(entry.videoId);
        thumbnail.initialize(DeveloperKey.DEVELOPER_KEY, thumbnailListener);
      } else {
        YouTubeThumbnailView thumbnail = (YouTubeThumbnailView) view.findViewById(R.id.thumbnail);
        YouTubeThumbnailLoader loader = thumbnailViewToLoaderMap.get(thumbnail);
        if (loader == null) {
          // 2) The view is already created, and is currently being initialized. We store the
          //    current videoId in the tag.
          thumbnail.setTag(entry.videoId);
        } else {
          // 3) The view is already created and already initialized. Simply set the right videoId
          //    on the loader.
          thumbnail.setImageResource(R.drawable.loading_thumbnail);
          loader.setVideo(entry.videoId);
        }
      }
      TextView label = ((TextView) view.findViewById(R.id.text));
      label.setText(entry.text);
      label.setVisibility(labelsVisible ? View.VISIBLE : View.GONE);
      return view;
    }

    private final class ThumbnailListener implements
        YouTubeThumbnailView.OnInitializedListener,
        YouTubeThumbnailLoader.OnThumbnailLoadedListener {

      @Override
      public void onInitializationSuccess(
          YouTubeThumbnailView view, YouTubeThumbnailLoader loader) {
        loader.setOnThumbnailLoadedListener(this);
        thumbnailViewToLoaderMap.put(view, loader);
        view.setImageResource(R.drawable.loading_thumbnail);
        String videoId = (String) view.getTag();
        loader.setVideo(videoId);
      }

      @Override
      public void onInitializationFailure(
          YouTubeThumbnailView view, YouTubeInitializationResult loader) {
        view.setImageResource(R.drawable.no_thumbnail);
      }

      @Override
      public void onThumbnailLoaded(YouTubeThumbnailView view, String videoId) {
      }

      @Override
      public void onThumbnailError(YouTubeThumbnailView view, ErrorReason errorReason) {
        view.setImageResource(R.drawable.no_thumbnail);
      }
    }

  }

  public static final class VideoFragment extends YouTubePlayerFragment
      implements OnInitializedListener {

    private YouTubePlayer player;
    private String videoId;

    public static VideoFragment newInstance() {
      return new VideoFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      initialize(DeveloperKey.DEVELOPER_KEY, this);
    }

    @Override
    public void onDestroy() {
      if (player != null) {
        player.release();
      }
      super.onDestroy();
    }

    public void setVideoId(String videoId) {
      if (videoId != null && !videoId.equals(this.videoId)) {
        this.videoId = videoId;
        if (player != null) {
          player.cueVideo(videoId);
        }
      }
    }

    public void pause() {
      if (player != null) {
        player.pause();
      }
    }

    @Override
    public void onInitializationSuccess(Provider provider, YouTubePlayer player, boolean restored) {
      this.player = player;
      player.addFullscreenControlFlag(YouTubePlayer.FULLSCREEN_FLAG_CUSTOM_LAYOUT);
      player.setOnFullscreenListener((MainActivity) getActivity());
      if (!restored && videoId != null) {
        player.cueVideo(videoId);
      }
    }

    @Override
    public void onInitializationFailure(Provider provider, YouTubeInitializationResult result) {
      this.player = null;
    }

  }

  private static final class VideoEntry {
    private final String text;
    private final String videoId;

    public VideoEntry(String text, String videoId) {
      this.text = text;
      this.videoId = videoId;
    }
  }

  // Utility methods for layouting.

  private int dpToPx(int dp) {
    return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
  }

  private static void setLayoutSize(View view, int width, int height) {
    LayoutParams params = view.getLayoutParams();
    params.width = width;
    params.height = height;
    view.setLayoutParams(params);
  }

  private static void setLayoutSizeAndGravity(View view, int width, int height, int gravity) {
    FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
    params.width = width;
    params.height = height;
    params.gravity = gravity;
    view.setLayoutParams(params);
  }

}

3 个答案:

答案 0 :(得分:1)

  

引起:android.view.InflateException:二进制XML文件行#22:   膨胀类片段错误

确保使用

import android.support.v4.app.Fragment;

并确保使用片段的Activity扩展FragmentActivity而不是常规Activity,

import android.support.v4.app.FragmentActivity;

获取FragmentActivity类。

答案 1 :(得分:0)

VideoListFragment类在MainActivity类中。但是inflator尝试加载来自VideoListDemoActivity类。检查xml布局并修复VideoListFragment的路径。

答案 2 :(得分:0)

它可能没有重构您的AndroidManifest.xml文件。请检查相同的