当前位置: 首页 > 知识库问答 >
问题:

如何使用HandlerThread类将单独的循环传递给线程

符鸣
2023-03-14

我有一个名为“bluetoothIn”的处理程序,我想使用HandlerThread类将其传递给一个单独的循环器,该类将提供循环器。然而,我需要将结果从“handleMessage(Message msg)”发回UI线程,因为我不能修改除主线程之外的其他线程的UI元素。

这是我的代码:

package com.uniproj.senseplate;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

@SuppressWarnings("unused")
public class MainActivity extends Activity {

  Button btnscan;
  TextView txtArduino, txtString, txtStringLength, calorie;
  Handler bluetoothIn;

  final int handlerState = 0;                        //used to identify handler message
  private BluetoothAdapter btAdapter = null;
  private BluetoothSocket btSocket; //= null;
  private StringBuilder recDataString = new StringBuilder();

  private ConnectedThread mConnectedThread;

  // SPP UUID service - this should work for most devices
  private static final UUID BTMODULEUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

  // String for MAC address
  private static String address;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    //Link the buttons and textViews to respective views                
    btnscan = (Button) findViewById(R.id.scanBtn);             
    txtString = (TextView) findViewById(R.id.txtString); 
    txtStringLength = (TextView) findViewById(R.id.testView1); 

    bluetoothIn = new Handler() {
        public void handleMessage(android.os.Message msg) {
            if (msg.what == handlerState) { 
                String readMessage = (String) msg.obj; 
                recDataString.append(readMessage);
                int endOfLineIndex = recDataString.indexOf("~"); 
                if (endOfLineIndex > 0) { 
                    String dataInPrint = recDataString.substring(0, endOfLineIndex); 
                    txtString.setText("Data Received = " + dataInPrint);                
                    int dataLength = dataInPrint.length();  
                    txtStringLength.setText("String Length = " + String.valueOf(dataLength));

                    if (recDataString.charAt(0) == '#') 
                    {
                        //get sensor value from string between indices 1-20
                        String weight = recDataString.substring(1, 20);
                        //update the textviews with sensor values
                        calorie.setText(weight + "kg");

                    }
                    recDataString.delete(0, recDataString.length());                    
                   // strIncom =" ";
                    dataInPrint = " ";
                }            
            }
        }
    };

    btAdapter = BluetoothAdapter.getDefaultAdapter(); // get Bluetooth adapter
    checkBTState();  

  // Set up onClick listeners for button to scan for data
    btnscan.setOnClickListener(new OnClickListener() {
      public void onClick(View v) {
        mConnectedThread.write("0");
      }
    });
}

  private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {

      return  device.createRfcommSocketToServiceRecord(BTMODULEUUID);
      //creates secure outgoing connecetion with BT device using UUID
  }

  @Override
  public void onResume() {
    super.onResume();

    //Get MAC address from DeviceListActivity via intent
    Intent intent = getIntent();

    //Get the MAC address from the DeviceListActivty via EXTRA
    address = intent.getStringExtra(DeviceListActivity.EXTRA_DEVICE_ADDRESS);

    //create device and set the MAC address
    BluetoothDevice device = btAdapter.getRemoteDevice(address);

    try {
        btSocket = createBluetoothSocket(device);
    } catch (IOException e) {
        Toast.makeText(getBaseContext(), "Socket creation failed", Toast.LENGTH_LONG).show();
    }  
    // Establish the Bluetooth socket connection.
    try 
    {
      btSocket.connect();
    } catch (IOException e) {
      try 
      {
        btSocket.close();
      } catch (IOException e2) 
      {
        //insert code to deal with this 
      }
    } 
    mConnectedThread = new ConnectedThread(btSocket);
    mConnectedThread.start();

    //I send a character when resuming.beginning transmission to check device is connected
    //If it is not an exception will be thrown in the write method and finish() will be called
    mConnectedThread.write("x");
  }

  @Override
  public void onPause() 
  {
    super.onPause();
    try
    {
    //Don't leave Bluetooth sockets open when leaving activity
      btSocket.close();
    } catch (IOException e2) {
        //insert code to deal with this 
    }
  }

 //Checks that the Android device Bluetooth is available and prompts to be turned on if off 
  private void checkBTState() {

    if(btAdapter==null) { 
        Toast.makeText(getBaseContext(), "Device does not support bluetooth", Toast.LENGTH_LONG).show();
    } else {
      if (btAdapter.isEnabled()) {
      } else {
        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBtIntent, 1);
      }
    }
  }

  //create new class for connect thread
  private class ConnectedThread extends Thread {
        private final InputStream mmInStream;
        private final OutputStream mmOutStream;

        //creation of the connect thread
        public ConnectedThread(BluetoothSocket socket) {
            btSocket = socket;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;

            try {
                //Create I/O streams for connection
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) { }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
        }

        public void run() {
            byte[] buffer = new byte[1024];  
            int bytes; 

            // Keep looping to listen for received messages
            while (true) {
                try {
                    bytes = mmInStream.read(buffer);
                    bluetoothIn.obtainMessage(handlerState, bytes, -1, buffer).sendToTarget(); 
                } catch (IOException e) {
                    break;
                }
            }
        }

        //write method
        public void write(String input) {
            byte[] msgBuffer = input.getBytes();//converts entered String into bytes
            try {
                mmOutStream.write(msgBuffer);//write bytes over BT connection via outstream
            } catch (IOException e) {  
                //if you cannot write, close the application
                Toast.makeText(getBaseContext(), "Connection Failed", Toast.LENGTH_LONG).show();
                finish();

              }
            }

        public class BluetoothInHandler extends Handler{
            private Looper sLooper = null;

            private Handler mWorkerThreadHandler;

            final int handlerState = 0;                        //used to identify handler message


            protected class WorkerArgs {
                Handler handler;
                String input;
                String output;
            }


            public BluetoothInHandler() {
                super();
                synchronized (BluetoothInHandler.class) {
                    if (sLooper == null) {
                        HandlerThread thread = new HandlerThread("AsyncWorker");
                        thread.start();

                        sLooper = thread.getLooper();
                    }
                }
                mWorkerThreadHandler = new WorkerHandler(sLooper);
            }

            @Override
            public void handleMessage(Message msg) {
                if (msg.what == handlerState) {
                    WorkerArgs args = (WorkerArgs) msg.obj;
                    String readMessage = args.output;
                    //your job;
                } else {
                    super.handleMessage(msg);
                }
            }

            public void write(String input) {
                WorkerArgs args = new WorkerArgs();
                args.handler = this;
                args.input = input;
                Message message = mWorkerThreadHandler.obtainMessage(handlerState);
                message.obj = args;
                mWorkerThreadHandler.sendMessage(message);
            }

            protected class WorkerHandler extends Handler {
                public WorkerHandler(Looper looper) {
                    super(looper);
                }



                @Override
                public void handleMessage(Message msg) {
                    if (msg.what == handlerState) {
                        WorkerArgs args = (WorkerArgs) msg.obj;
                        //the code here run in a thread, not in the ui thread
                        //do your job like:
                        byte[] bytes = mmInStream.read(buffer);


                        args.output = new String(bytes);
                        Message message = args.handler.obtainMessage(handlerState);
                        message.obj = args;
                        message.sendToTarget();
                    }
                }
            }

        }

        }//ConnectedThread End              

}

共有2个答案

景安翔
2023-03-14

对不起,我弄错了。我认为错误是由代码<code>bluetoothIn引起的。获取消息(handlerState,字节,-1,缓冲区)

更改为

bluetoothIn.obtainMessage(handlerState, bytes,-1, new String(缓冲区)). sendToTarget();

删除我写的代码。没用的。

谢雅珺
2023-03-14

RunOnUi可能是个不错的选择

runOnUiThread(new Runnable() {
    @Override
    public void run() {
    // Do whatever you need to do on the UI here
    }
});
 类似资料:
  • 问题内容: 谁能建议我如何将参数传递给线程? 另外,它如何用于匿名类? 问题答案: 你需要将构造函数中的参数传递给Runnable对象: 然后调用它:

  • 我是selenium初学者,只是想把webDriver传递给另一个类,但没有成功。程序应该打开浏览器(“Google”)并在主类中键入一些单词,在第二个类中应该按下“Google”按钮。 以下是我的主要课程: 这是我想从主驱动程序中使用的类。 当我运行它时,它对我说: 传递:main失败:printOnScreen java.lang.NullPointerException 我做错了什么?谢谢高

  • 编辑了我的问题以进行澄清和编码: 我的目标是将我的String数据从我的后台线程传递到我的主应用程序线程。感谢任何帮助。 下面是创建主后台线程的代码。这是位于我的Server.java类 下面是连接客户端时调用的代码,它位于我的 Controller.java类中。 然后程序为我的客户机创建两个后台线程,一个管理接收消息,一个管理发送消息。 然后,线程成功地创建了inputstream,并将对象传

  • 问题内容: 我创建了一个参数化的Jenkins作业,该作业将变量从Java传递到。 这是Java: 所以这很简单,因为我只是将s 传递给工作。但是,我现在想使用Jenkins中的A将A传递给工作。 我看到的一件事是Jenkins中的拥有一个和。因此,甚至不知道如何从Java将其设置为参数。 这可能吗? 问题答案: 这是一个可运行的类。使用apache-httpclient(4.5.1)和相关的ja

  • 问题内容: 我在MVC框架的View类上有3套。我想在controll类中引用它们。有人可以告诉我这实现了吗?下面是事件控制器。EventView类由addEvent,editEvent,deleteEvent组成,如何在Controller类中为其侦听器。有人可以在Controller类的顶部演示使用示例代码吗? 第二个问题,我只能从类本身更新a ,因此 在View类中具有代码是一种不好的做法,

  • 问题内容: 我是Docker的新手,目前尚不清楚如何从容器访问外部数据库。硬编码连接字符串的最佳方法是吗? 问题答案: 您可以使用该标志将环境变量传递到您的容器。 启动脚本的示例: 或者,如果您不希望在命令行中使用,等显示该值,则可以直接从当前环境中获取该值,如果您不带: 如果您有许多环境变量,尤其是要保密的话,可以使用env文件: --env-file标志将文件名作为参数,并期望每行采用VAR