简体   繁体   English

使用线程从 Activity 更新 Fragment

[英]Update Fragment from Activity with Thread

First, I'm sorry for my poor English, I hope you could understand me even so.首先,我很抱歉我的英语不好,但我希望你能理解我。

The APP :应用程序:

  • 1 Activity with 3 Fragments and PageAdaptater OK 1 个带有 3 个片段和 PageAdaptater OK 的活动

  • Collect data from an Bluetooth device.从蓝牙设备收集数据。 OK好的

  • Update TextView in an fragment each time data is collected in the MainActivity via Handler.每次通过 Handler 在 MainActivity 中收集数据时更新片段中的 TextView。

Below my code :在我的代码下面:

MainActivity :主要活动 :

public class MainActivity extends FragmentActivity {

    private PagerAdapter mPagerAdapter;
    private static final String TAG = "bluetooth2";
    private String btaddr = "20:14:09:17:00:40";
    Handler h;
    final int RECIEVE_MESSAGE = 1;        // Status  for Handler
    private BluetoothAdapter btAdapter = null;
    private BluetoothSocket btSocket = null;
    private StringBuilder sb = new StringBuilder();
    private ConnectedThread mConnectedThread;
    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.viewpager);

        // Création de la liste de Fragments que fera défiler le PagerAdapter
        List<Fragment> fragments = new Vector<Fragment>();

        // Ajout des Fragments dans la liste
        fragments.add(Fragment.instantiate(this,HomeFragment.class.getName()));
        fragments.add(Fragment.instantiate(this,NormalFragment.class.getName()));
        fragments.add(Fragment.instantiate(this,ConfigFragment.class.getName()));

        // Création de l'adapter qui s'occupera de l'affichage de la liste de
        // Fragments
        this.mPagerAdapter = new MyPagerAdapter(super.getSupportFragmentManager(), fragments);

        ViewPager pager = (ViewPager) super.findViewById(R.id.viewpager);
        // Affectation de l'adapter au ViewPager
        pager.setAdapter(this.mPagerAdapter);

        h = new Handler() {
            public void handleMessage(android.os.Message msg)  {
                switch (msg.what) {
                case RECIEVE_MESSAGE:                                                   // if receive massage
                    byte[] readBuf = (byte[]) msg.obj;
                    String strIncom = new String(readBuf, 0, msg.arg1);                 // create string from bytes array
                    sb.append(strIncom);                                                // append string
                    int endOfLineIndex = sb.indexOf("\r\n");                            // determine the end-of-line
                    if (endOfLineIndex > 0) {                                            // if end-of-line,
                        String sbprint = sb.substring(0, endOfLineIndex);               // extract string
                        sb.delete(0, sb.length());                                      // and clear

                        Log.d(TAG, "...String:"+ sb.toString() +  "Byte:" + msg.arg1 + "...");
                        //My question : How to send data to fragment from here ?

                        break;
                    }
                }
            };
        };

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

        checkBTState();


      }

      private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
          if(Build.VERSION.SDK_INT >= 10){
              try {
                  final Method  m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
                  return (BluetoothSocket) m.invoke(device, MY_UUID);
              } catch (Exception e) {
                  Log.e(TAG, "Could not create Insecure RFComm Connection",e);
              }
          }
          return  device.createRfcommSocketToServiceRecord(MY_UUID);
      }

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

        Log.d(TAG, "...onResume - try connect...");

        // Set up a pointer to the remote node using it's address.
        BluetoothDevice device = btAdapter.getRemoteDevice(btaddr);

        // Two things are needed to make a connection:
        //   A MAC address, which we got above.
        //   A Service ID or UUID.  In this case we are using the
        //     UUID for SPP.

        try {
            btSocket = createBluetoothSocket(device);
        } catch (IOException e) {
            errorExit("Fatal Error", "In onResume() and socket create failed: " + e.getMessage() + ".");
        }

        // Discovery is resource intensive.  Make sure it isn't going on
        // when you attempt to connect and pass your message.
        btAdapter.cancelDiscovery();

        // Establish the connection.  This will block until it connects.
        Log.d(TAG, "...Connecting...");
        try {
          btSocket.connect();
          Log.d(TAG, "....Connection ok...");
        } catch (IOException e) {
          try {
            btSocket.close();
          } catch (IOException e2) {
            errorExit("Fatal Error", "In onResume() and unable to close socket during connection failure" + e2.getMessage() + ".");
          }
        }

        // Create a data stream so we can talk to server.
        Log.d(TAG, "...Create Socket...");

        mConnectedThread = new ConnectedThread(btSocket);
        mConnectedThread.start();
      }

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

        Log.d(TAG, "...In onPause()...");

        try     {
          btSocket.close();
        } catch (IOException e2) {
          errorExit("Fatal Error", "In onPause() and failed to close socket." + e2.getMessage() + ".");
        }
      }

      private void checkBTState() {
        // Check for Bluetooth support and then check to make sure it is turned on
        // Emulator doesn't support Bluetooth and will return null
        if(btAdapter==null) {
          errorExit("Fatal Error", "Bluetooth not support");
        } else {
          if (btAdapter.isEnabled()) {
            Log.d(TAG, "...Bluetooth ON...");
          } else {
            //Prompt user to turn on Bluetooth
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, 1);
          }
        }
      }

      private void errorExit(String title, String message){
        Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).show();
        finish();
      }

      public class ConnectedThread extends Thread {
            private final InputStream mmInStream;
            private final OutputStream mmOutStream;

            public ConnectedThread(BluetoothSocket socket) {
                InputStream tmpIn = null;
                OutputStream tmpOut = null;

                // Get the input and output streams, using temp objects because
                // member streams are final
                try {
                    tmpIn = socket.getInputStream();
                    tmpOut = socket.getOutputStream();
                } catch (IOException e) { }

                mmInStream = tmpIn;
                mmOutStream = tmpOut;
            }

            public void run() {
                byte[] buffer = new byte[256];  // buffer store for the stream
                int bytes; // bytes returned from read()

                // Keep listening to the InputStream until an exception occurs
                while (true) {
                    try {
                        // Read from the InputStream
                        bytes = mmInStream.read(buffer);        // Get number of bytes and message in "buffer"
                        h.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget();     // Send to message queue Handler
                    } catch (IOException e) {
                        break;
                    }
                }
            }

            /* Call this from the main activity to send data to the remote device */
            public void write(String message) {
                Log.d(TAG, "...Data to send: " + message + "...");
                byte[] msgBuffer = message.getBytes();
                try {
                    mmOutStream.write(msgBuffer);
                } catch (IOException e) {
                    Log.d(TAG, "...Error data send: " + e.getMessage() + "...");
                  }
            }
        }

}

HomeFragment (receiver) : HomeFragment(接收器):

public class HomeFragment extends Fragment {


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        View myInflatedView = inflater.inflate(R.layout.home_layout, container, false);

        return myInflatedView;
    }

}

Home Layout :家居布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="20dp"
        android:text="DATA" />

</LinearLayout>

In this situation, for you, how can I send data easly from handler in activity to the HomeFragment and update the textview inside?在这种情况下,对您来说,如何轻松地将数据从活动中的处理程序发送到 HomeFragment 并更新里面的文本视图?

I'm very new in Java, and most tutorials are in English, same thing about documentation so it's hard to learn alone correctly...我是 Java 新手,大多数教程都是英文的,文档也一样,所以很难正确地单独学习......

I tried many snippets found on stackoverflow without success, and now I am a bit lost..我尝试了很多在 stackoverflow 上找到的代码片段都没有成功,现在我有点迷茫了..

EDIT 1:编辑 1:
As requested, here the code for PagerAdaptater :根据要求,这里是PagerAdaptater的代码:

public class MyPagerAdapter extends FragmentPagerAdapter {

    private final List<Fragment> fragments;

    //On fournit à l'adapter la liste des fragments à afficher
    public MyPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
        super(fm);
        this.fragments = fragments;
    }

    @Override
    public Fragment getItem(int position) {
        return this.fragments.get(position);
    }

    @Override
    public int getCount() {
        return this.fragments.size();
    }
}

EDIT 2:编辑2:
Updated HomeFragment :更新的HomeFragment

public class HomeFragment extends Fragment {

    TextView data;
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        View myInflatedView = inflater.inflate(R.layout.home_layout, container, false);
        data= (TextView) myInflatedView.findViewById(R.id.data);

        return myInflatedView;
    }
      public void change(String txt){
          data.setText(txt); //Don't WORK "NullPointerException"
          Log.d("TEST", "...String:"+ txt +  "..."); //Work
        }

}

EDIT 3 :编辑 3:

The solution, check if data is not null before do setText.解决办法,在做setText之前先检查data是否不为null。

public void change(String txt){
            if(data != null){
                data.setText(str);
            }
          Log.d("TEST", "...String:"+ txt +  "..."); //Work
        }

You could keep a reference to your HomeFragment in your MainActivity like this and add it to your pager adapter:您可以像这样在 MainActivity 中保留对 HomeFragment 的引用,并将其添加到寻呼机适配器:

public class MainActivity extends FragmentActivity {
    // instanciate other variables
    private HomeFragment myHomeFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        super.setContentView(R.layout.

        List<Fragment> fragments = new Vector<Fragment>();

        this.myHomeFragment = fragment.instantiate(this,HomeFragment.class.getName());

        fragments.add(myHomeFragment);
        fragments.add(Fragment.instantiate(this,NormalFragment.class.getName()));
        fragments.add(Fragment.instantiate(this,ConfigFragment.class.getName()));

        ...
    }
}

Then, in your HomeFragment, declare a public method that takes a string and sets the text of the TextView and call it in your handler:然后,在您的 HomeFragment 中,声明一个公共方法,该方法接受一个字符串并设置 TextView 的文本并在您的处理程序中调用它:

myHomeFragment.setTextView(sb.toString());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM