I've got a Fragment (fragment_address) that is shown in a Fragment container in my main activity. My fragment_address Fragment brings up a list of paired devices. When a listed item is clicked the Fragment is replaced in my main activity by another fragment. This Fragment has buttons to bring up other fragments. This all works fine until I click a button to bring up a new Fragment and the fragment_address is shown in the background as well as my new fragment. As the address fragment is only ever needed once is there a way to ensure this fragment is destroyed when replaced ?
My Main Activity.
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();
}
}
The 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>
My Address Fragment
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);
}
}
}
}
My address 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>
And my OnStart that is replacing the MainFragment with the ControlOutputs Fragment when butControlOutputs is called.
@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
I've had the addToBackStack in and removed it again. I thought the ft.replace would destroy the previous Fragment if the previous one was not added to the back stack ??
I've added this to the OnClickListener. It adds the MainFragment but always returns 'null' for the AddressFragment.
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();
If you are using dynamic fragments, set up via a FragmentTransaction , you could run a transaction to replace() the old fragment with the new one.
As Fragment is embedded inside an Activity, it will be killed when Activity is killed. As contents of activity are first killed, fragment will be destroyed just before activity gets destroyed.
If you don't remove manually these fragments, they are still attached to the activity. Your activity is not destroyed so these fragments are too. To remove (so destroy) these fragments, you can call:
You need to use findFragmentById for Fragment from XML file.
call this on MainActivity
Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.main_frag)
And this on OnClick Listener Method
if(fragment != null)
getSupportFragmentManager().beginTransaction().remove(fragment).commit();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With