【问题标题】:You cannot start a load for a destroyed activity in relativelayout image using glide您无法使用 glide 开始加载 relativelayout 图像中的已破坏活动
【发布时间】:2016-08-23 06:21:37
【问题描述】:

我正在使用 relativelayout 设置图像。为什么我没有使用 imageview 意味着,在 relativelayout 图像中,我正在设置图标。

我不知道 glide 到底是什么问题。我在下面发布了堆栈跟踪和相关代码:

Logcat:

 FATAL EXCEPTION: main
   Process: com.app.steve, PID: 15928 
 java.lang.IllegalArgumentException: You cannot start a load for a destroyed activity
   at com.bumptech.glide.manager.RequestManagerRetriever.assertNotDestroyed(RequestManagerRetriever.java:134)
   at com.bumptech.glide.manager.RequestManagerRetriever.get(RequestManagerRetriever.java:102)
   at com.bumptech.glide.Glide.with(Glide.java:644)
                                                                    at com.app.steve.TabMorePagesDetailActivity$allPageDetails.onPostExecute(TabMorePagesDetailActivity.java:1050)
     at com.app.steve.TabMorePagesDetailActivity$allPageDetails.onPostExecute(TabMorePagesDetailActivity.java:885)
    at android.os.AsyncTask.finish(AsyncTask.java:632)
    at android.os.AsyncTask.access$600(AsyncTask.java:177)
   at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:645)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:135)
    at android.app.ActivityThread.main(ActivityThread.java:5221)
   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:899)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

TabMorePagesDetailActivity.java:

RelativeLayout rlPageCoverImg;

rlPageCoverImg = (RelativeLayout)findViewById(R.id.rl_club_cover_img);

@Override
        protected void onPostExecute(String response) {
            super.onPostExecute(response);

            dialog.dismiss();
        ............

    String coverIMGurl = cover_avatar_obj.getString("url");

    Log.e("ImgURL", coverIMGurl);

 Glide.with(TabMorePagesDetailActivity.this).load(coverIMGurl).asBitmap().signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
                                        .into(new SimpleTarget<Bitmap>(500, 500) {

    @Override
    public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
    Drawable drawable = new BitmapDrawable(getResources(), resource);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                                            rlPageCoverImg.setBackground(drawable);
    }
    }
    });

    }else {

    rlPageCoverImg.setBackgroundResource(R.drawable.bg_golive);

    }



    @Override
 protected void onDestroy()
 {
    super.onDestroy();
    Glide.clear(rlPageCoverImg);

 }

layout.xml:

 <RelativeLayout
            android:id="@+id/rl_club_cover_img"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:background="@drawable/cancel_image" >

  // Inside this relativelayout image, I'm using buttons and icons


 </RelativeLayout>

【问题讨论】:

    标签: android android-glide


    【解决方案1】:

    用途:

    Glide.with(getApplicationContext()).load(...)

    代替:

    Glide.with(TabMorePagesDetailActivity.this).load(...)

    希望能解决你的问题~

    注意:如果您决定使用applicationContext,请参阅Glide image loading with application context

    【讨论】:

    • 还通过获取和使用 ApplicationContext 解决了这个问题: Glide.with(context.getApplicationContext()) .using(new FirebaseImageLoader()) .load(storageReference) .signature(new StringSignature(uri.toString ())) .diskCacheStrategy(DiskCacheStrategy.ALL) .placeholder(placeHolder) .into(imageView);
    • 这将阻止它崩溃,但即使活动已被破坏,仍会使用资源来加载图像。
    • 请参阅 stackoverflow.com/a/32887693/389649 了解为什么在 Glide 中使用应用程序上下文不是一个好主意。
    • 我尝试使用您的解决方案,但我的应用程序崩溃了
    • 使用应用程序上下文(除非需要)完全破坏了 Android 上下文模型的目的。系统根据关联的上下文决定释放或保留在内存中、执行或保留的资源。完成的 Activity 应该释放它的资源。
    【解决方案2】:

    您可以简单地检查上下文是否被手动销毁;

    if (context == null) {
        return
    } else if (context !is Application) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            if (context is FragmentActivity) {
                if ((context as FragmentActivity).isDestroyed) {
                    return
                }
            } else if (context is Activity) {
                if ((context as Activity).isDestroyed) {
                    return
                }
            }
        }
    }
    

    这也可以表示为 Kotlin 扩展函数:

    /**
     * Return true if this [Context] is available.
     * Availability is defined as the following:
     * + [Context] is not null
     * + [Context] is not destroyed (tested with [FragmentActivity.isDestroyed] or [Activity.isDestroyed])
     */
    fun Context?.isAvailable(): Boolean {
        if (this == null) {
            return false
        } else if (this !is Application) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                if (this is FragmentActivity) {
                    return !this.isDestroyed
                } else if (this is Activity) {
                    return !this.isDestroyed
                }
            }
        }
        return true
    }
    

    【讨论】:

    • FragmentActivity 不是 Activity 吗?
    【解决方案3】:

    灵感来自 GitHub thread,我在加载任何图像之前使用它

    final Context  context = getApplication().getApplicationContext();
    
    if (isValidContextForGlide(context)){
                    // Load image via Glide lib using context
                   
      }
    
     public static boolean isValidContextForGlide(final Context context) {
        if (context == null) {
            return false;
        }
        if (context instanceof Activity) {
            final Activity activity = (Activity) context;
            if (activity.isDestroyed() || activity.isFinishing()) {
                return false;
            }
        }
        return true;
    }
    

    【讨论】:

      【解决方案4】:

      除非你真的需要,否则请不要使用Glide.with(getApplicationContext()),原因如下: Glide image loading with application context

      正确答案如下: https://github.com/bumptech/glide/issues/1484#issuecomment-365625087

      在 Kotlin 中,可以写成扩展函数:

      fun Context.isValidGlideContext() = this !is Activity || (!this.isDestroyed && !this.isFinishing)
      

      【讨论】:

        【解决方案5】:

        几天前我遇到了同样的问题。我已经解决了这个问题,以代表当前类上下文内存传递应用程序上下文内存。

        也许它会帮助你:-

        使用此代码

         Glide.with(getApplicationContext())
                   .load(coverIMGurl)
                   .asBitmap()
                   .signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
                                            .into(new SimpleTarget<Bitmap>(500, 500) {....}
        

        即使您遇到此问题,请仔细阅读本文“https://github.com/bumptech/glide/issues/1097

        此问题概述:这是 Glide 库的问题。

        【讨论】:

        • 如果是fragment..怎么办?
        • getActivity().getApplicationContext(); @Abhishek
        • 返回当前进程的单个全局应用程序对象的上下文。这通常只应在您需要一个生命周期与当前上下文分开的上下文时使用,该上下文与进程的生命周期而不是当前组件相关联 @Abhishek 在片段的情况下,您需要使用 getActivity().getApplicationContext( )
        • 那么在recyclerview中怎么做呢?
        • @Dr.aNdRO 与 recyclerview 适配器的构造函数一起传递,例如 Adapter adp = new Adapter(getApplicationContext(),list_of data),并在适配器中使用它。
        【解决方案6】:

        在使用 Glide 加载图像之前试试这个,在我的例子中 mirefer 是一个 StorageReference,miimagen 是一个 ImageView。我用这个解决了这个问题。希望对你有帮助。

        if (!this.isFinishing ()) {
                        // Load the image using Glide
                        Glide.with(YourActivity.this)
                                .using(new FirebaseImageLoader())
                                .load(mirefer)
                                .into(miimagen);
                    }
        

        【讨论】:

          【解决方案7】:

          使用具有正确生命周期的参数设置 Glide。例如:在自定义视图中使用Glide.with(this) 而不是Glide.with(getContext())

          【讨论】:

          • 这样你为每个项目视图持有者初始化滑行,我认为这对性能没有好处
          【解决方案8】:

          这是一个 Kotlin 扩展,将上面的几个答案组合在一起 - thisthisthis

          /**
           * Returns true when [Context] is unavailable or is about to become unavailable
           */
          fun Context?.isDoomed(): Boolean = when (this) {
              null -> true
              is Application -> false
              is Activity -> (this.isDestroyed or this.isFinishing)
              else -> false
          }
          

          【讨论】:

            【解决方案9】:

            不要只在适配器中使用从活动中获取的上下文作为 context=this 而是使用 context.getApplicationContext();

            【讨论】:

            • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
            【解决方案10】:

            另一种方法是检查activity是否被销毁,然后加载到UI元素中。

            if (!newActivty.isDestroyed()){
               ...
            }
            

            【讨论】:

              【解决方案11】:

              在 frament 的视图模型中你好 即使您按下后退按钮并退出程序,活动上下文也会保留。 回到程序,你不需要重新赋值上下文,因为上下文是静态的

              @Override
                  public void onBindViewHolder(@NonNull final viewholder viewholder, final int i) {
                      final Model_Post model_post = list.get(i);
                      Log.e(TAG, "onBindViewHolder: "+model_post.getImageurl());
              
                      Glide.with(MainActivity.activity)
                              .load(Uri.parse(model_post.getImageurl()))
                              .diskCacheStrategy(DiskCacheStrategy.ALL)
                              .into(viewholder.itemsPostBinding.imgvItempost);
              
                  }

              您必须在主要活动中执行此操作:

              public static AppCompatActivity activity;
              
              @Override
              protected void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);
                  activity = MainActivity.this;
              }
              

              【讨论】:

              • 不不不。您永远不应该将活动存储为静态变量。这将导致内存泄漏。 android-developers.googleblog.com/2009/01/…
              • 那么如何在适配器中设置上下文来使用glide呢?我的滑翔在 recyclerview 的适配器中
              【解决方案12】:

              请使用 Glide.with(holder.itemView.getContext()).load....... 它解决了我的问题参考https://github.com/bumptech/glide/issues/2690

              【讨论】:

              • 这样你为每个项目视图持有者初始化滑行,我认为这对性能没有好处
              【解决方案13】:

              只需使用这个帮助类:

              /**
               * @Lukas Niessen
               */
              public class GlideUsus {
              
                  public static final String TAG = "GlideUsus";
              
                  public interface Interface {
                      void doIfValidContext(RequestManager requestManager);
                  }
              
                  public static void execute(Context context, GlideUsus.Interface action) {
                      if (isValidContextForGlide(context)) {
                          action.doIfValidContext(Glide.with(context));
                      } else {
                          // nothing
                          Log.v(TAG, "Loading image failed");
                      }
                  }
              
                  public static boolean isValidContextForGlide(final Context context) {
                      if (context == null) {
                          return false;
                      }
                      if (context instanceof Activity) {
                          final Activity activity = (Activity) context;
                          if (activity.isDestroyed() || activity.isFinishing()) {
                              return false;
                          }
                      }
                      return true;
                  }
              }
              

              用法:

              GlideUsus.execute(mContext, (a -> a.load(uri).into(image)));
              

              【讨论】:

                【解决方案14】:

                在活动中我使用 Glide.with(getApplicatonContext()) 和 在适配器中我使用 Glide.with(myContext.getApplicatonContext())

                //It works for me fine.
                
                //for adapter
                
                Context myContext;
                
                //also initilize in `oncreateViewHolder`
                
                @Override
                    public MessagesHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
                        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_messages_layout, parent, false);
                        myContext = parent.getContext();
                        return new MessagesHolder(view);
                    }
                

                【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-10-18
                • 2023-04-03
                • 2017-02-08
                • 1970-01-01
                • 2013-11-16
                相关资源
                最近更新 更多