0

I am working on an Android app and using the TabLayout with two fragments, Map and Discovery. In the Discovery fragment, I have a ListView that I am using to display devices that the app has connected to. I am trying to add a feature that will cause the Map fragment to be loaded once an entry in the ListView is clicked. An attempt at implementing this feature was done by adding the code

Fragment fragment = new MapFragment();
FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.content_map,fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

to the OnClickListener of the ListView where R.id.content_map is the id of the layout file used with the MapFragment class. I found the above code here. Below are the DiscoveryFragment and MapFragment class definitions.

public class DiscoveryFragment extends Fragment {
    private DhcpInfo mDhcpInfo = null;
    private ArrayList<String> mArrayList = null;
    private final int TASK_COMPLETE = 1;
    private Handler mHandler = null;
    private final String IP_KEY = "IPs";
    private DiscoveryArrayAdapter mArrayAdapter = null;
    private final String ROBOT_ID = "create2";
    private AppDatabase db = null;
    private int mTaskCounterVar = 0;

    public DiscoveryFragment() {
        // This is an anonymous class which extends the Handler class
        // Handler object is attached to the UI thread
        mHandler = new Handler(Looper.getMainLooper()) {
            @Override
            public void handleMessage(@NonNull Message message) {
                // Get the message string from the Message
                super.handleMessage(message);
                Bundle bundle = message.getData();
                ArrayList<String> msgs = bundle.getStringArrayList(IP_KEY);
                if(msgs != null) {
                    mArrayList.addAll(msgs);
                }
                mArrayAdapter.notifyDataSetChanged();
            }

        };
    }
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WifiManager wifiManager = (WifiManager) getContext().getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        mDhcpInfo = wifiManager.getDhcpInfo();
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

        ListView listView = null;
        final View discoveryView = inflater.inflate(R.layout.fragment_discovery,container,false);
        mArrayList = new ArrayList<String>();
        new Thread(new FindRobotTask()).start();
        db = Room.databaseBuilder(discoveryView.getContext(), AppDatabase.class, "AppDatabase").build();
        // Setup a new thread to perform network operations

        // Use the ArrayAdapter to register new content to the ListView
        mArrayAdapter = new DiscoveryArrayAdapter(discoveryView.getContext(), mArrayList);

        FloatingActionButton fab = (FloatingActionButton) discoveryView.findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new FindRobotTask()).start();
                mArrayAdapter.notifyDataSetChanged();
            }
        });

        listView = (ListView)discoveryView.findViewById(R.id.listview);
        listView.setAdapter(mArrayAdapter);
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Fragment fragment = new MapFragment();
                FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
                fragmentTransaction.replace(R.id.content_map,fragment);
                fragmentTransaction.addToBackStack(null);
                fragmentTransaction.commit();
            }
        });

        return discoveryView;
    }

    class FindRobotTask implements Runnable {

        // Implement the run method
        public void run() {
            Bundle bundle = new Bundle();
            Message message = mHandler.obtainMessage();
            ArrayList<String> ipArrayList = new ArrayList<String>();
            try {
                String msg = "Hello";
                String ip = "";
                InetAddress group = InetAddress.getByName("224.3.29.71");
                MulticastSocket sock = new MulticastSocket();
                sock.joinGroup(group);
                byte[] bytes = msg.getBytes();
                DatagramPacket hi = new DatagramPacket(bytes, bytes.length, group, 10000);
                sock.send(hi);
                byte[] buf = new byte[1000];
                String recvMsg = "";
                InetAddress address = null;
                for(int i = 0; i < 10 && !"iRobot Create 2".equals(recvMsg); i++) {
                    DatagramPacket recv = new DatagramPacket(buf, buf.length);
                    sock.receive(recv);
                    recvMsg = new String(recv.getData(), 0, recv.getLength());
                    address = recv.getAddress();
                }
                ip = address.getHostAddress();
                List<Robot> robotsWithIp = db.robotDao().loadByIp(ip);

                // If a corresponding table entry is not found,
                // add the robot to the database.
                if(mTaskCounterVar == 0) {
                    if(robotsWithIp.size() == 0) {
                        ipArrayList.add(recvMsg + ": " + ip);
                        Robot robot = new Robot(recvMsg, ip);
                        db.robotDao().insert(robot);
                        mTaskCounterVar++;
                        // Else load the robot from the database
                    } else if (robotsWithIp.size() > 0) {
                        for(Robot robot : robotsWithIp) {
                            if(robot != null) {
                                ipArrayList.add(robot.name + ": " + robot.ip);
                            }
                        }
                        mTaskCounterVar++;
                    }
                }
                sock.leaveGroup(group);
                sock.close();
            } catch(UnknownHostException e) {
                e.printStackTrace();
            } catch(IOException e) {
                e.printStackTrace();
            }

            bundle.putStringArrayList(IP_KEY,ipArrayList);
            message.setData(bundle);
            mHandler.sendMessage(message);
        }
    }

}
public class MapFragment extends Fragment {
    public MapFragment() {

    }
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.fragment_map, container, false);
    }
}

However, when I run the app, the DiscoveryFragment does not get replaced with the MapFragment upon clicking an entry in the list view. Can anyone point me to where I might be going wrong? I believe it may be the id passed to the replace method, but I'm really not sure.

Farzad Kamali
  • 751
  • 2
  • 6
  • 24
  • just a note, listview is deprecated for the most part in android, the new standard is recyclerview – beastlyCoder Jul 02 '20 at 20:33
  • To replace, the container which was used to display 'DiscoveryFragment` should be used in the `FragmentTransaction`. After replacement, it will start showing `MapFragment` in the same container. – cgb_pandey Jul 03 '20 at 02:23
  • @cgb_pandey Thanks for the response. I tried substituting in the `replace` call R.id.content_map with R.id.content_discovery which is the id of the container used to display the discovery fragment, but things still are not working properly. – brlauwer324 Jul 06 '20 at 18:06
  • And if you want to load `MapFragment` from `DiscoveryFragment` on `onClick()` method then, I think you don't need the `TabsLayout` – cgb_pandey Jul 07 '20 at 02:14

0 Answers0