非静态方法问题

Non static method issue

通过 android studio 运行 代码检查后,强调 MainHandler 应该是静态的。我将 class 移动到 static 但现在它抱怨说 "Non-Static method remainingSecondsChanged(int) cannot be referenced from a static context"

public class CountDownView extends FrameLayout {

    private static void remainingSecondsChanged(int newVal) {
        mRemainingSecs = newVal;
        if (mListener != null) {
            mListener.onRemainingSecondsChanged(mRemainingSecs);
        }

        if (newVal == 0) {
            // Countdown has finished.
            setVisibility(View.INVISIBLE);
            if (mListener != null) {
                mRemainingSecondsView.setText(null);
                mRemainingSecondsView.setBackgroundResource(R.drawable.bracket_view_finder);
                mListener.onCountDownFinished();
            }
        } else {
            Locale locale = getResources().getConfiguration().locale;
            String localizedValue = String.format(locale, "%d", newVal);
            mRemainingSecondsView.setText(localizedValue);

            // Schedule the next remainingSecondsChanged() call in 1 second
            mHandler.sendEmptyMessageDelayed(SET_TIMER_TEXT, 1000);
        }
    }

    public void startCountDown(int sec) {
        if (sec < 0) {
            return;
        }
        if (sec == 0) {
            cancelCountDown();
        }
        mRemainingSecondsView.setBackgroundResource(R.drawable.bracket_count_down);
        setVisibility(View.VISIBLE);
        remainingSecondsChanged(sec);
    }

    private static class MainHandler extends Handler {

        @Override
        public void handleMessage(Message message) {
            if (message.what == SET_TIMER_TEXT) {
                remainingSecondsChanged(mRemainingSecs - 1);
            }
        }
    }

    private static final MainHandler mHandler = new MainHandler();

}

知道如何解决吗?

我不是 android 程序员,但也许与其创建扩展 Handler 的内部 class,不如像这样创建私有字段:

private Handler handler = new Handler() {
   public void handleMessage(Message msg) {
      //call your non static method here
   }
}

这个 Whosebug post here 解释了为什么内部 classes 应该是静态的,这与代码分析器抱怨它的原因几乎相同,假设如果你想要包含 class 的成员可以从你的内部访问 class 你可以让它成为非静态的

修改MainHandler的构造函数接收回调接口

public MainHandler(Callback cb){
  this.mCallBack = cb;
}

然后在handleMessage调用回调接口执行方法

 public void handleMessage(Message message) {
            if (message.what == SET_TIMER_TEXT) {
                mCallBack.someMethod();1);
            }
        }

在片段声明接口

public interface Callback
{
 void someMethod();
}

让你的片段实现它。

private final MainHandler mHandler = new MainHandler(this);

然后在执行调用

        remainingSecondsChanged(mRemainingSecs - 1);

这不是最好的方法,但它是您当前设计中最快的方法。

首先...为什么 Studio 会显示该消息?

背景

每个 Handler 都与一个 Thread 关联,同一 Thread 上的所有 Handler 对象共享一个公共 Looper 对象,它们 post 并阅读他们的消息。事情是......当这些对象是非静态的......非静态内部classes持有对其外部class的隐式引用。因此 Handler 将持有对您的 Activity 的引用,如果此 Handler 有延迟消息,您的 Activity 将无法在处理此消息之前被垃圾回收.

您可以阅读更多相关信息 here

解决方案

至于你的问题。您已经做的第一件事就是让您的 Handler 成为 static 内部 class。现在,为你的外部 class 创建一个 WeakReference(可以是一个 Activity 或者我相信在这种情况下,你的 CountDownView)。

现在尝试将您的 Handler 更改为类似这样的内容(您可以参考您的 CountDownView 而不是 Activity):

private static class MainHandler extends Handler {

    private final WeakReference<YourActivity> mActivity;

    public MainHandler(YourActivity activity) {
        mActivity = new WeakReference<YourActivity>(activity);
    }

    @Override
    public void handleMessage(Message message) {
        YourActivity activity = mActivity.get();
        if (activity != null) {
            if (message.what == SET_TIMER_TEXT) {
                activity.remainingSecondsChanged(mRemainingSecs - 1);
            }
        }            
    }
}

并像这样实例化它:

// this is a reference to your Activity, or your CountDownView, wherever your method is.
private final MainHandler mHandler = new MainHandler(this);