【问题标题】:Java, using an interface as a callbackJava,使用接口作为回调
【发布时间】:2023-03-09 16:22:01
【问题描述】:

我一直在为 Android 开发一个简单的触摸处理程序,它可以触发诸如 onUpdate(触摸屏幕时)之类的回调,而无需设置线程。我的问题是我对 Java 的了解相当有限,我做不到,因为我对如何使用接口知之甚少。我很确定我的问题可能是一个简单的错字之类的,但是当我从触摸处理程序(处理触摸信息)执行方法时,我得到了 NullPointerException,这样我就可以在主活动类中做我需要的事情.

这是主要的类代码(从不相关的东西中删除):

//package and imports

public class Test extends Activity implements TouchHelper {

    StringBuilder builder = new StringBuilder();
    TextView textView;
    TouchReader touchReader;
    List<TouchTable> touchTablesArray;
    TouchTable touchTable;
    public static final String Tag = "TouchTest";

        @Override
        public void onCreate(Bundle savedInstanceState) 
        {
            super.onCreate(savedInstanceState);
            textView = new TextView(this);
            Log.d(Tag, "TextView initialized " + textView);
            textView.setText("Touch and drag (multiple fingers supported)!");
            touchReader = new TouchReader(textView);
            Log.d(Tag, "touchReader initialized");
            touchTablesArray = touchReader.getTouchTables();
            setContentView(textView);
        }

        @Override
        public void onTouchUpdate(int pointerId)
        {
            Log.d(Tag, "onTouchUpdate called");
            touchTable = touchTablesArray.get(pointerId);
            Log.d(Tag, "touchTable get successful");
            //writing on stringbuilder
        }
    }

这是处理程序本身的代码:

//package and imports

public class TouchReader implements OnTouchListener
{
    public final static String Tag = "TouchReader";
    List<TouchTable> touchTables;
    TouchHelper helper;
    TouchTable touchTable = new TouchTable();

    public TouchReader(View view)
    {
        view.setOnTouchListener(this);
        touchTables = new ArrayList<TouchTable>(10);
        Log.d(Tag, "TouchReader initialized");
    }

    public boolean onTouch(View v, MotionEvent event)
    {
        synchronized(this)
        {
            //all the common code handling the actual handling, with switches and such
            touchTables.add(pointerId, touchTable); //obviously the pointerId is defined earlier
            Log.d(Tag, "Values updated");
            helper.onTouchUpdate(pointerId); //the exception is here
            Log.d(Tag, "Update called");
        }
        return true;
    }
    public List<TouchTable> getTouchTables()
    {
        synchronized(this)
        {
            return touchTables;
        }
    }
}

如您所见,该错误很可能是由于我无法正确使用界面,但所有官方文档都让我更加困惑。

最后是界面的小代码:

//package

public interface TouchHelper 
{
    public void onTouchUpdate(int pointerId);
}

我希望这个问题不会太无聊,不能在这里发布:)

编辑:感谢大家的帮助,最后我遵循了 Bughi 的解决方案。

【问题讨论】:

    标签: java android interface callback touch


    【解决方案1】:

    我知道这已经过时了,但我自己却被困在了这个问题上。上面山姆的帖子让我想到了这一点。
    我最后添加了一个 onAttach 方法,该方法检查接口是否已初始化以及是否已实现到它与之交互的主要活动。我在主要活动中添加了一个 Log.i 进行测试。

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mainActivityCallback = (OnSomethingSelectedListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnSomethingSelectedListener");
        }
    }
    

    【讨论】:

      【解决方案2】:

      您的TouchHelper helper; 为空,它需要一个接口实例才能调用其上的方法 - 在您的情况下,是实现您的接口的主要活动类 -

      为监听器设置一个方法

      public void setOnTouchListener(TouchHelper helper)
      {
          this.helper = helper;
      }
      

      然后在创建时调用它:

      public class Test extends Activity implements TouchHelper {
          ...
          @Override
          public void onCreate(Bundle savedInstanceState) 
          {
              ...
              touchReader = new TouchReader(textView);
              touchReader.setOnTouchListener(this);
              ...
          }
      }
      

      同时为你的 on touch 方法添加一个空检查:

      public boolean onTouch(View v, MotionEvent event)
      {
          synchronized(this)
          {
              //all the common code handling the actual handling, with switches and such
              touchTables.add(pointerId, touchTable); //obviously the pointerId is defined earlier
              Log.d(Tag, "Values updated");
              if (helper != null)
                  helper.onTouchUpdate(pointerId); //the exception is here
              Log.d(Tag, "Update called");
          }
          return true;
      }
      

      【讨论】:

      • 谢谢,这很有魅力。显然这个错误是愚蠢的,但因为我知道“实例化”接口的工作方式与普通类不同,所以我迷路了。
      【解决方案3】:

      如果 NullPointerException 在这里:

      helper.onTouchUpdate(pointerId);
      

      那么简单helper为null,你在哪里初始化呢?

      我看到你定义了它:

      TouchHelper helper;
      

      但是你有过吗?

      helper = ...
      

      【讨论】:

        【解决方案4】:

        尝试在你的构造函数中初始化它;所有未初始化的引用都设置为 null。

        // I see no reason why this should be a member variable; make it local
        StringBuilder builder = new StringBuilder();
        TextView textView;
        TouchReader touchReader;
        List<TouchTable> touchTablesArray;
        TouchTable touchTable;
        public TouchReader(View view)
        {
            // textView is null
            // touchReader is null
            view.setOnTouchListener(this);
            // why "10"?  why a List of touchTables and a touchTable member variable?  why both?
            touchTables = new ArrayList<TouchTable>(10);
            Log.d(Tag, "TouchReader initialized");
            // touchTable is null;
        }
        

        【讨论】:

        • 10 因为我正在对 ArrayList 进行一些试验,我选择了该值是因为...好吧,尝试将 10 根以上的手指放在手机上:/ touchTable 成员变量是一个缓冲区我写入数据,然后将其保存到 ArrayList。可能不是最有效的方法,但它是迄今为止最简单的
        • 正如我所指出的,您还有很多其他问题。你会很好地解决这些问题。您是新人,因此您应该知道,这对您和那些贡献时间来投票有用的答案并接受最能回答您问题的答案的人都有好处。
        • 如果您的意思是您的其他 cmets,我会在构造函数或代码的其他部分中为这些变量赋值。制作Listener函数后代码完美运行
        • 如果我知道该怎么做,我会的
        • 看到向上箭头了吗?单击它们以对答案进行投票。看到每个答案旁边的复选标记了吗?点击最能回答您问题的那一项。
        【解决方案5】:

        helper 在您的TouchReader 中为空

        要解决此问题,请将 TouchReader 设为 TouchHelper

        public TouchReader(View view, TouchHelper helper) {
            ...
            this.helper = helper;   
            ...
        }
        

        然后在你的活动中:

        touchReader = new TouchReader(textView, this);
        

        【讨论】:

          【解决方案6】:

          TouchReader 中定义了TouchHelper,但在代码中没有创建对象或将现有对象分配给该属性。所以当你尝试使用它时它仍然是 null。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-10-16
            • 2021-06-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多