Android:处理来自非 UI 线程的 onTouch 事件

Android: Handling onTouch events from non UI thread

我不确定我正在尝试做的事情是否有意义,但我会试一试: 我的 phone 用作客户端,我需要将有关运动事件的数据发送到服务器。 我正在处理与 AsyncTask 的通信,所以我想在我的 AsyncTask class 中实现 onTouch 方法。 我让我的 AsyncTask 实现了 View.OnTouchListener 但事件并没有真正到达我的 AsyncTask 中的 onTouch 方法。 我猜我遗漏了一些非常基本的东西..

这是 AsyncTask 代码:

public class tpAsyncTask extends AsyncTask<String,String,String> implements View.OnTouchListener {

Context context;
boolean isCancelled = false;
float prevX;
float prevY;
Socket socket;
ObjectOutputStream oos;
private final static String TAG = "ME ASYNCTASK LOGGER: ";    

public tpAsyncTask(Context context){
    this.context = context;
}

@Override
protected String doInBackground(String... strings) {
    String IP = strings[0];
    String port = strings[1];

    try {
        InetAddress inetAddress = InetAddress.getByName(IP);
        socket = new Socket(inetAddress,Integer.parseInt(port));
        OutputStream os = socket.getOutputStream();
        oos = new ObjectOutputStream(os);
        while(!isCancelled()) {
            Thread.sleep(1000);
        }
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    return null;
}

@Override
protected void onCancelled() {
    super.onCancelled();
    try {
        oos.flush();
        oos.close();
        socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
// PROBLEM IS THAT THE APP NEVER REACH HERE
        if(!isCancelled()) {
            switch(motionEvent.getAction()) {
                case MotionEvent.ACTION_MOVE:
                {
                    Log.d(TAG, "ACTION MOVE IS PREFORMED");
                }
                case MotionEvent.ACTION_DOWN:
                {
                    Log.d(TAG, "ACTION DOWN IS PREFORMED");
                }
            }
        }
        return false;
    }}

谢谢

编辑,解决:

正如此处评论的许多人所说,我必须将我的 onTouch 实现附加到特定视图。 因此,由于我需要我的 onTouch 事件来包含所有屏幕尺寸,我只是创建了一个我的相对布局的对象并将其传递给我的 asyncTask(实现 OnTouchListener)的构造函数,并在我设置的构造函数上 myRelativeLayout.setOnTouchListerner(this) . 成功了——asyncTask 中的 onTouch 方法现在在我触摸屏幕时被调用。

非常感谢大家。

有点缺乏信息。您是否使用

将 asyncTask 正确地放置在 onTouchListener 视图中
view.setOnTouchListener(yourAsyncTask);

请注意,您的 AsyncTask 对象必须是 运行 对象(而不是新实例或匿名实例)。因此,我建议您在启动 运行 您的 asyncTask 时添加侦听器。

如果您已经这样做了,我建议您 post 更多信息(您的 activity 代码、asyncTask 启动和 setOnTouchListener 部分)。

编辑: 代码示例:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    View viewToTouchWithReact=findViewById(R.id.yourViewId);
    AsyncTask task=/**.AsynTask creation and launch.**/
    viewToTouchWithReact.setOnTouchListener(task);
}

做那样的事情。如果没有启动 asyncTask 的代码和 activity 代码,我不能更精确。抱歉

无法访问代码,因为 AsyncTask 不是用户可以 'touched' 的 UI 元素。您应该将侦听器添加到视图,然后启动异步任务:

view.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent motionEvent) {
        switch(motionEvent.getAction()) {
            case MotionEvent.ACTION_MOVE:
            {
                tpAsyncTask<String,String,String> task = new tpAsyncTask<>();
                task.execute(motionEvent);
                Log.d(TAG, "ACTION MOVE IS PREFORMED");
            }
            case MotionEvent.ACTION_DOWN:
            {
                Log.d(TAG, "ACTION DOWN IS PREFORMED");
            }
        }
        return false;
    }
});

我认为你的客体关系有点由内而外。与其让你的 AsyncTask 拥有或成为 OnTouchListener,不如让你的 OnTouchListener(它总是在 UI 线程中调用)触发 AsyncTask

如果您的 AsyncTask 在完成后更新了 UI,那么您将需要跟踪 运行 AsyncTask,以便在activity 已暂停。否则,让您的 AsyncTask 一劳永逸可能没问题。 (创建它,执行它,让它超出范围。)