更换时销毁碎片

fat*_*ing 6 android android-fragments

我有一个 Fragment (fragment_address),它显示在我的主要活动的 Fragment 容器中。我的 fragment_address Fragment 会显示已配对设备的列表。单击列出的项目时,我的主要活动中的 Fragment 将被另一个 Fragment 替换。该片段具有用于调出其他片段的按钮。这一切都很好,直到我单击一个按钮来调出一个新的 Fragment 并且 fragment_address 显示在背景中以及我的新片段中。由于地址片段只需要一次,有没有办法确保在替换时销毁该片段?

我的主要活动。

import android.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity implements AddressFragment.OnAddressListener {
    private static final String TAG = "Main Activity";
    // MAC-address of Bluetooth module (you must edit this line)
    private static String address = "No Device Selected";
    private static String deviceName = "No Device Selected";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onAddressChanged(String itemAddress, String itemName){
        // Set your address
        address = itemAddress;
        deviceName = itemName;
        MainFragment fragMain = new MainFragment();
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        fragMain.setVariables(address, deviceName);
        ft.replace(R.id.main_frag, fragMain);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        ft.commit();
    }
}
Run Code Online (Sandbox Code Playgroud)

xml。

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

    <fragment
        class="com.ming.pondcontroller.AddressFragment"
        android:id="@+id/main_frag"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

我的地址片段

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

import java.util.ArrayList;
import java.util.Set;

public class AddressFragment extends Fragment {

    private static final String TAG = "Address Activity";
    private BluetoothAdapter BA = null;
    private Set<BluetoothDevice> pairedDevices;
    LayoutInflater inflater2;
    ListView lv;
    String address;
    String itemName;
    String itemString;
    OnAddressListener mListener;

    public AddressFragment() {
        // Required empty public constructor
    }

    // Container Activity must implement this interface
    public interface OnAddressListener {
        public void onAddressChanged(String address, String itemName);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        inflater2 = inflater;
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_address, container, false);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnAddressListener ) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnAddressListener");
        }
    }

    @Override
    public void onStart(){
        super.onStart();
        lv = (ListView)getView().findViewById(R.id.listView);
        BA = BluetoothAdapter.getDefaultAdapter();
        checkBTState();

        // get paired devices
        pairedDevices = BA.getBondedDevices();
        ArrayList list = new ArrayList();
        // get a list of paired devices
        for(BluetoothDevice bt:pairedDevices){
            list.add(bt.getName()+"\n"+bt.getAddress());
        }
        // display the list in the list view
        final ArrayAdapter adapter = new ArrayAdapter(inflater2.getContext(),android.R.layout.simple_list_item_1,list);
        lv.setAdapter(adapter);

        // onItemClick Listener
        lv.setOnItemClickListener(new AdapterView.OnItemClickListener(){
            @Override
            public void onItemClick(AdapterView<?> adapterView,View view, int position, long l){
                // get the text of the item clicked from position
                itemString = (String)(lv.getItemAtPosition(position));
                // get last 17 characters for MAC address
                address = itemString.substring(itemString.length()-17);
                itemName = itemString.substring(0,itemString.length()-17);
                // send strings back to main Activity
                mListener.onAddressChanged(address,itemName);
            }
        }); //end of onClickListener
    }

    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(BA==null) {
            Log.d("Fatal Error", "Bluetooth not support");
        } else {
            if (BA.isEnabled()) {
                Log.d(TAG, "...Bluetooth ON...");
            } else {
                //Prompt user to turn on Bluetooth
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, 1);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的地址 Fragment xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorMainBack"
    tools:context="com.ming.pondcontroller.AddressFragment">
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:id="@+id/textView"
        android:background="@color/colorPrimary"
        android:textColor="@color/colorWhite"
        android:textSize="20dp"
        android:text="Select Device"/>
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/textView"
        android:background="@color/colorTextBack">
    </ListView> />
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

我的 OnStart 在调用 butControlOutputs 时将 MainFragment 替换为 ControlOutputs Fragment。

@Override
public void onStart() {
    super.onStart();
    TextView tv = (TextView)getView().findViewById(R.id.textIn);
    tv.setText(address);
    TextView tv2 = (TextView)getView().findViewById(R.id.textIn2);
    tv2.setText(deviceName);
    // Get ID's of buttons
    Button butSyncData = (Button)getActivity().findViewById(R.id.butSyncData);
    Button butControlOutputs = (Button)getActivity().findViewById(R.id.butControlOuts);
    Button butDateTime = (Button)getActivity().findViewById(R.id.butDateTime);
    Button butPreferences = (Button)getActivity().findViewById(R.id.butPreferences);
    Button butFullData = (Button)getActivity().findViewById(R.id.butFullData);
    // Create OnClick listener for each button
    butSyncData.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            Log.d(TAG,"Button Get Now data Clicked");
            if(ConStatus == true){
                mConnectedThread.write(MainFragment.getNowData); // Sync Data to start
            }else if(!(address == "No Device Selected")) {
                btAdapter = BluetoothAdapter.getDefaultAdapter();       // get Bluetooth adapter
                BluetoothDevice device = btAdapter.getRemoteDevice(address);

                ConnectThread ct = new ConnectThread(device);
                ct.start();
            }
        }
    });

    butControlOutputs.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            Log.d(TAG,"Control Outputs Clicked");
            // TODO rest of Control Outputs Launch
            OutputsFragment fragOutputs = new OutputsFragment();
            FragmentTransaction ft = getFragmentManager().beginTransaction();
            ft.replace(R.id.main_frag,fragOutputs);
            ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
            ft.commit();
        }
    });

    butDateTime.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            Log.d(TAG,"Date & Time Clicked");
            Toast.makeText(getActivity(),"Date & Time Clicked",Toast.LENGTH_SHORT).show();
            // TODO rest of Date Time Launch
        }
    });

    butPreferences.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            Log.d(TAG,"Preferences Clicked");
            Toast.makeText(getActivity(),"Preferences Clicked",Toast.LENGTH_SHORT).show();
            // TODO rest of Control Outputs Launch
        }
    });

    butFullData.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            Log.d(TAG,"Full Data Clicked");
            Toast.makeText(getActivity(),"Full Data Clicked",Toast.LENGTH_SHORT).show();
            // TODO rest of Control Outputs Launch
        }
    });

    // Start thread to connect to bluetooth
    if(!(address == "No Device Selected")) {
        btAdapter = BluetoothAdapter.getDefaultAdapter();       // get Bluetooth adapter
        BluetoothDevice device = btAdapter.getRemoteDevice(address);

        ConnectThread ct = new ConnectThread(device);
        ct.start();
    }
} // End of on start
Run Code Online (Sandbox Code Playgroud)

我已经将 addToBackStack 放入并再次删除它。我认为 ft.replace 会破坏前一个 Fragment 如果前一个没有添加到后堆栈中?

我已将此添加到 OnClickListener。它添加了 MainFragment,但始终为 AddressFragment 返回“null”。

Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_frag);
        if(fragment != null) {
            Log.d("In OAC","Fragment Not NULL");
            getSupportFragmentManager().beginTransaction().remove(fragment).commit();
        }else{
            Log.d("In OAC","Fragment NULL");
        }
        MainFragment fragMain = new MainFragment();
        FragmentTransaction ft = getFragmentManager().beginTransaction();
        fragMain.setVariables(address, deviceName);
        ft.add(R.id.main_frag, fragMain);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        ft.commit();
Run Code Online (Sandbox Code Playgroud)

Emd*_*ain 1

如果您不手动删除这些片段,它们仍会附加到活动中。您的活动不会被破坏,因此这些碎片也会被破坏。要删除(销毁)这些片段,您可以调用:

您需要对 XML 文件中的片段使用 findFragmentById。

在MainActivity上调用它

Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_frag)
Run Code Online (Sandbox Code Playgroud)

这在OnClick Listener 方法上

 if(fragment != null)
        getSupportFragmentManager().beginTransaction().remove(fragment).commit();
Run Code Online (Sandbox Code Playgroud)