【问题标题】:Best approach to access an Activity on the inside of a (custom) view/dialog?在(自定义)视图/对话框内部访问活动的最佳方法?
【发布时间】:2020-08-11 14:45:42
【问题描述】:

我的应用中只有一项活动。在我将视图和对话框静态存储在活动中之前,我可以从任何地方访问它们。但我知道这是不好的做法,因为它会导致内存泄漏。

所以我将它们设置为非静态的,但现在我需要在视图层次结构的深处引用我的活动,以访问存储在活动中的视图和对话框。

示例:

我的 MainActivity 有一个名为 a 的对话框和一个名为 b 的自定义视图。 b的onClick方法如何显示对话框a

或在代码中:

public class MainActivity extends Activity {
    private CustomDialog a;
    private CustomView b;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        a = new CustomDialog(this);
        b = new CustomView(this);
    }
}


public class CustomView extends Button implements OnClickListener {
    public CustomView(Context context) {
        super(context);
        setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        //wants to show dialog a
        MainActivity.a.show(); //Not possible -> a is not static
        mainActivity.a.show(); //<-- needs a reference of the activity
                               //    but where from?
    }
}

MainActivity mainActivity = (MainActivity) getContext(); 不起作用,因为 getContext() 并不总是活动上下文。

更新:

我在下面发布了答案! 由于某些原因,StackOverflow 只让我在两天内接受自己的答案

【问题讨论】:

    标签: android android-activity sharedpreferences android-view android-context


    【解决方案1】:

    我不知道您的视图层次结构到底是什么样的。

    我将您的问题描述为: Activity A 有一个recyclerview R,现在R 中的每个viewholder H 应该可以触发A 中的某个方法。

    在这种情况下,将您的活动引用传递给您的 recyclerview 适配器,然后适配器将其传递给 ViewHolder 是可行的。 然后在您的(查看者)视图的 onClick 方法中使用它。 在这里,您可以使用“回调”模式。 stackoverflow上有很多关于这个的帖子,例如here.

    所以实施步骤是:

    1. 定义接口
    2. 让您的活动实现该接口
    3. 让您的适配器将接口作为构造函数参数并传递您的活动。 (在此示例中:您必须使用 viewHolder 重复该步骤,从适配器传递接口)
    4. 在 onClick 方法中使用此接口方法 -> 这将触发您的活动方法

    实现取决于实际的层次结构。如果您的其他视图位于片段中,那么您也可以使用(共享)ViewModel。 根据您的图片,我首先考虑的是回调模式方法。

    【讨论】:

    • 也是 Sid 的一个好建议。这实际上取决于您的观点之间的关系。如果您不想在活动内部定义 onClick 方法,那么您可以使用类似于他的回调方法来执行此操作。那么除了this你只需要传递interface(由你的activity实现)
    • @Mano176 您要求一种“最佳”方式。展开上下文似乎不应该这样做。 android 文档建议在与活动通信时使用接口。在示例中,活动与片段通信,但它也可以是任何其他类。 developer.android.com/training/basics/fragments/…
    【解决方案2】:

    您可以在 MainActivity 中覆盖 onClick;类定义本身可能不需要这样做。

    public class MainActivity extends Activity {
        private CustomDialog a;
        private CustomView b;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            a = new CustomDialog(this);
            b = new CustomView(this);
            
            b.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    a.show();
                }
            });
    
        }
    }
    

    这是 android 中非常常见的模式,我不知道您的视图层次结构是什么样的,但在大多数情况下它应该可以工作。 我无法理解为什么扩展Button 的任何类都需要实现View.OnClickListener。在活动中创建侦听器或让MainActivity 实现OnClickListener 更有意义。

    【讨论】:

    • 在某些情况下我会这样做。但由于我所有的 CustomViews 都应该做同样的事情,我不想在我的活动中覆盖 onClicks。那时我的活动课也会变得很长。但是谢谢你的建议! :)(顺便说一句,扩展按钮和实现 onclicklistener 的视图仅用于示例)
    【解决方案3】:

    几分钟后,这里的答案被证明是正确的。 不知道作者为什么删了,但是里面有this的链接回答:

    private static Activity unwrap(Context context) {
        while (!(context instanceof Activity) && context instanceof ContextWrapper) {
            context = ((ContextWrapper) context).getBaseContext();
        }
        return (Activity) context;
    }
    

    因此,每当您需要活动时,您只需致电Activity activity = unwrap(getContext());

    我不知道它是否真的打算这样做,或者它是否是一种解决方法,但它确实发挥了作用(至少在我的情况下)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-12
      • 2016-11-03
      • 1970-01-01
      • 1970-01-01
      • 2011-12-06
      • 1970-01-01
      相关资源
      最近更新 更多