android.content.res.Resources $ NotFoundException:无法找到资源ID

时间:2018-01-11 07:49:30

标签: java android android-fragments android-recyclerview

在我的RecyclerView中,我需要将部分项目替换为我的片段。 我跟着this answer by Victor Cruz,我能够实现我想要的目标。

一切正常但我面临一个严重的问题,即我只在我的RecyclerView的最后一项中得到Resources$NotFoundException Unable to find resource ID,请注意,这个问题仅在最后一项中发生,其他人正常工作。

我尝试过的步骤:

  1. 我试图在R.java文件中查找resource ID,但都是徒劳的。

  2. 我尝试过减少和增加RecyclerView中的项目数量,但问题仍然存在。

  3. 搜索其他相关答案,例如将相同的ID分配给父布局作为传递替换片段。
  4. 尝试捕获异常但失败了,因为我认为只有在最后一项的情况下才能在创建时找到布局文件。
  5. 检查是否由于任何类型转换错误而发生。
  6. 请在我做错的地方提出建议。我很乐意提供任何其他相关细节。

    发布问题5天后(并且在这一周内苦苦挣扎),我无法解决问题。 我已经制作了一个小型示例应用来执行此特定任务,您可以download the code from here.

    请帮我解决这个问题。

    编辑:发布代码:

    private void flipcard(final RecyclerView.ViewHolder holder)
    {
        final MyHolder myHolderflipcard= (MyHolder) holder;
                // Delete old fragment
                int containerId = myHolderflipcard.container.getId();// Get container id
                Fragment oldFragment = ((FragmentActivity) context).getFragmentManager().findFragmentById(containerId);
                if(oldFragment != null)
                {
                    ((FragmentActivity) context).getFragmentManager().beginTransaction().remove(oldFragment).commit();
                }
                int newContainerId = getUniqueId();
                // Set the new Id to our know fragment container
                myHolderflipcard.container.setId(newContainerId);
                // Just for Testing we are going to create a new fragment according
                // if the view position is pair one fragment type is created, if not
                // a different one is used.
                {
                    Fragment f;
                    f = new CardBackFragment();
                    // Then just replace the recycler view fragment as usually
                    ((FragmentActivity) context).getFragmentManager().beginTransaction()
                            .setCustomAnimations(
                                    R.animator.card_flip_right_in,
                                    R.animator.card_flip_right_out,
                                    R.animator.card_flip_left_in,
                                    R.animator.card_flip_left_out)
                            .addToBackStack(null)
                            .replace(newContainerId, f).commit();
    
                    myHolderflipcard.cardView.setVisibility(View.GONE);
                }
    }
    // Method that could us an unique id
    private int getUniqueId(){
        return (int)
                SystemClock.currentThreadTimeMillis();
    }
    

    这是我的logcat,如果它可以有用。

    E/UncaughtException: android.content.res.Resources$NotFoundException: Unable to find resource ID #0x1678
                                                                                  at android.content.res.Resources.getResourceName(Resources.java:2209)
                                                                                  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:886)
                                                                                  at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
                                                                                  at android.app.BackStackRecord.run(BackStackRecord.java:834)
                                                                                  at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
                                                                                  at android.app.FragmentManagerImpl$1.run(FragmentManager.java:447)
                                                                                  at android.os.Handler.handleCallback(Handler.java:739)
                                                                                  at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                                  at android.os.Looper.loop(Looper.java:135)
                                                                                  at android.app.ActivityThread.main(ActivityThread.java:5292)
                                                                                  at java.lang.reflect.Method.invoke(Native Method)
                                                                                  at java.lang.reflect.Method.invoke(Method.java:372)
                                                                                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
                                                                                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
    
    E/AndroidRuntime: FATAL EXCEPTION: main
                                                                           Process: **app package name //intentionally written**, PID: 3136
                                                                           android.content.res.Resources$NotFoundException: Unable to find resource ID #0x1678
                                                                               at android.content.res.Resources.getResourceName(Resources.java:2209)
                                                                               at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:886)
                                                                               at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
                                                                               at android.app.BackStackRecord.run(BackStackRecord.java:834)
                                                                               at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
                                                                               at android.app.FragmentManagerImpl$1.run(FragmentManager.java:447)
                                                                               at android.os.Handler.handleCallback(Handler.java:739)
                                                                               at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                               at android.os.Looper.loop(Looper.java:135)
                                                                               at android.app.ActivityThread.main(ActivityThread.java:5292)
                                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                                               at java.lang.reflect.Method.invoke(Method.java:372)
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
    

2 个答案:

答案 0 :(得分:3)

这个问题很有意思。在调试您的示例应用程序一段时间之后,这是我的发现:

  • 缺少的resource id是已创建片段的ID - CardBackFragment
  • 在替换并提交片段
  • 后动态给出resource id

对于我刚才所说的教授,这是我调试你的应用时的截图,注意显示的 id enter image description here 这是调试器告诉它缺少的缺少的id: enter image description here

要明确的是,newContainerId转换为十六进制ID 就在这里(对不起我的英语不好)

那么这里发生了什么?

答案在于代码执行行的方式: myHolderflipcard.cardView.setVisibility(View.GONE); 在提交要显示的片段之后,这就是触发器。

以下是发生的事情: 当您告诉卡片视图消失时,最后一项将从ui - >中删除。因为它是从ui中删除的,它是回收站视图中的最后一项 - > recycler view的高度缩短以最小化view。最后一项会发生错误,因为recycler view了解保留问题的row layout是空的,而且它是最后一项 - >最后一项是转移到上面的问题行。同时,将fragment插入framelayout的帖子未完成。所以当它完成并且它试图找到containerid时,它找不到它。因此,崩溃。

所以修复它的方法是等待框架完全添加然后你删除问题

以下是修复:

  • myHolderflipcard.cardView.setVisibility(View.GONE);方法

  • 中删除flipcard
  • 在外面创建一个:private MyHolder curHolder;

  • 创建一个runnable来隐藏CardView:

    private Handler handler = new Handler();
    
    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
           Log.d("mId", String.valueOf(curHolder.container.getId()));
            curHolder.cardView.setVisibility(View.GONE);
    

    // handler.postDelayed(this,500);         }     };

  • 在提交完成后发布:

            Fragment f;
            f = new CardBackFragment();
            // Then just replace the recycler view fragment as usually
            ((FragmentActivity) context).getFragmentManager().beginTransaction()
                    .setCustomAnimations(
                            R.animator.card_flip_right_in,
                            R.animator.card_flip_right_out,
                            R.animator.card_flip_left_in,
                            R.animator.card_flip_left_out)
                    .addToBackStack(null)
                    .replace(newContainerId, f).commit();
            // Once all fragment replacement is done we can show the hidden container
            handler.post(runnable);
    

虽然它发生得非常快。如果您想确保在任何情况下成功替换片段,您可以使用handler.postDelayed(runnable, 100);

这是完整的代码(因为我的英语非常糟糕,所以我发布以防万一)

    private void flipcard(final RecyclerView.ViewHolder holder)
    {
        final MyHolder myHolderflipcard= (MyHolder) holder;

        String nim=mysr_id.get(Integer.parseInt(mpref.getradio_button_value()));
        Pattern pattern = Pattern.compile("[0-9]+");
        Matcher matcher = pattern.matcher(nim);
        if (matcher.find())
        {
            currentsrid=Integer.parseInt(matcher.group(0));

            if (currentsrid!=flag)
            {
                flag = Integer.parseInt(matcher.group(0));
                // Delete old fragment
                int containerId = myHolderflipcard.container.getId();// Get container id
                Fragment oldFragment = ((FragmentActivity) context).getFragmentManager().findFragmentById(containerId);
                if(oldFragment != null)
                {
                    ((FragmentActivity) context).getFragmentManager().beginTransaction().remove(oldFragment).commit();
                }
                int newContainerId = 0;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                    newContainerId = View.generateViewId();
                }

                // Set the new Id to our know fragment container

                myHolderflipcard.container.setId(newContainerId);

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    curHolder = myHolderflipcard;
                }


                // Just for Testing we are going to create a new fragment according
                // if the view position is pair one fragment type is created, if not
                // a different one is used.


                {
                    Fragment f;
                    f = new CardBackFragment();
                    // Then just replace the recycler view fragment as usually
                    ((FragmentActivity) context).getFragmentManager().beginTransaction()
                            .setCustomAnimations(
                                    R.animator.card_flip_right_in,
                                    R.animator.card_flip_right_out,
                                    R.animator.card_flip_left_in,
                                    R.animator.card_flip_left_out)
                            .addToBackStack(null)
                            .replace(newContainerId, f).commit();
                    // Once all fragment replacement is done we can show the hidden container
                    handler.post(runnable);

                    //myHolderflipcard.container.setVisibility(View.VISIBLE);
                    //myHolderflipcard.radioGroup.setVisibility(View.GONE);
                    //myHolderflipcard.tvQuestion.setVisibility(View.GONE);
//                    myHolderflipcard.cardView.setVisibility(View.GONE);
                }

            }else
            {
               // backtoorignal=false;
                // ((FragmentActivity)context). getFragmentManager().popBackStack();
            }

        }

    }

    private MyHolder curHolder;
    private Handler handler = new Handler();

    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
           Log.d("mId", String.valueOf(curHolder.container.getId()));
            curHolder.cardView.setVisibility(View.GONE);
        }
    };

答案 1 :(得分:1)

只需检查小东西。
可能不是原因,但通常情况下,当TextView上的setText带有整数(数字)时。 像贝娄一样

int a = 999;    
myTextView.setText(a);`

所以我假设您在 CardBackFragment

中使用带有数字的setText调用