【问题标题】:Android: Handling onTouch events from non UI threadAndroid:处理来自非 UI 线程的 onTouch 事件
【发布时间】:2017-03-14 16:33:16
【问题描述】:

我不确定我正在尝试做的事情是否有意义,但我会试一试: 我的手机充当客户端,我需要将有关运动事件的数据发送到服务器。 我正在处理与 AsyncTask 的通信,因此我想在 AsyncTask 类中实现 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 方法。

非常感谢大家。

【问题讨论】:

  • 在 PostExecute() 中设置 onTouchListener()

标签: android android-asynctask motionevent


【解决方案1】:

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

正确地将您的 asyncTask 作为 onTouchListener 放置在视图上
view.setOnTouchListener(yourAsyncTask);

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

如果您已经这样做了,我建议您发布更多信息(您的活动代码、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 的代码和活动代码,我就不能更精确了。对不起

【讨论】:

  • 这一定是我缺少的部分,但是,我仍然不确定我是否理解你。您能详细说明一下代码示例吗?我应该将监听器添加到哪个视图?
  • 您必须将侦听器添加到要对用户触摸做出反应的视图中。
【解决方案2】:

无法访问代码,因为 AsyncTask 不是用户可以“触摸”的 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;
    }
});

【讨论】:

  • 据我了解,您提供的内容与 Kevin Krumwiede 提供的内容相似,我的问题是 - 它不会导致 UI 线程上的工作过多吗?我的意思是为每个动作事件创建并执行一个 asyncTask?
  • AsyncTask 的想法是在另一个线程上运行代码。但是,如果您有很多运动事件,您可以将它们收集到一个列表中,然后一次性发送。
【解决方案3】:

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

如果您的 AsyncTask 在完成后更新 UI,那么您需要跟踪运行 AsyncTasks 以便在活动暂停时取消它们。否则,可以让您的AsyncTask 即发即弃。 (创建它,执行它,然后让它超出范围。)

【讨论】:

  • 感谢您的见解,但它不会导致 UI 线程上的工作过多吗?我的意思是每秒启动几十个 AsyncTasks?而不是简单地从一个 asynctask 监听 touchevents 并节省为每个动作事件设置每个 asynctask 的所有开销?
  • @Noam AsyncTask 将在后台线程中完成大部分工作。在您对其进行测试之前,我不会认为开销会太大。如果是这样,您可以完全取消 AsyncTask 并使用可以同时处理多个请求的网络库。
  • 或者您可以在OnTouchListener 中排队触摸事件,然后每隔几秒启动一个任务来发送它们。
猜你喜欢
  • 1970-01-01
  • 2011-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多