简体   繁体   中英

How to cast context into listener in BroadcastReceiver's onReceive which is registering from Fragment?

This is the BroadcastReceiver in which context is cast into listener interface:

public class StatusChangeReceiver extends BroadcastReceiver {
    private IStatusChangeListener listener;

    @Override
    public void onReceive(Context context, Intent intent) {
        listener = (IStatusChangeListener) context; // getting error in this line when using LocalBroadcastManager

        if (NetworkUtil.isNetworkConnected()) {
            listener.onConnected();
        } else {
            listener.onDisconnected();
        }
    }
}

This is the interface:

public interface IStatusChangeListener {
    void onConnected(String status);
    void onDisonnected(String status);
}

Now I'm implementing the IStatusChangeListener interface in a Fragment like below:

public class MainFragment extends Fragment implements IStatusChangeListener {
    //some codes

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        StatusChangeReceiver r = new StatusChangeReceiver();
        LocalBroadcastManager.getInstance(getContext()).registerReceiver(r, new IntentFilter("connectionStatus"));
        //getContext().registerReceiver(r, new IntentFilter("connectionStatus"));
    }

    @Override
    void onConnected(String status) {
        //some log here
    }

    @Override
    void onDisonnected(String status) {
        //some log here
    }
}

When I use getContext().registerReceiver(r, new IntentFilter("connectionStatus")); then I get no error but I get no call in the implemented listener's methods in the Fragment.

When I use LocalBroadcastManager.getInstance(getContext()).registerReceiver(r, new IntentFilter("connectionStatus")); then I get java.lang.ClassCastException error:

<ContextName> cannot be cast to IStatusChangeListener

So what is the solution to overcome this problem? Is there any standard way to implement BroadcastReceiver which casts context into listener?

You have to check if the context is instance of IStatusChangeListener or not.

public class StatusChangeReceiver extends BroadcastReceiver {
    private IStatusChangeListener listener;

    @Override
    public void onReceive(Context context, Intent intent) {
        if(context instanceof IStatusChangeListener){
           
        listener = (IStatusChangeListener) context; // getting error in this line //when using LocalBroadcastManager

        if (NetworkUtil.isNetworkConnected()) {
            listener.onConnected();
        } else {
            listener.onDisconnected();
        }
        }
    }
}

In your activity

public class YourActivity extends AppCompatActivity implements IStatusChangeListener {

    MainFragment mainFragment;
    
    @Override
    public void onConnected(String status) {
        if (mainFragment!=null){
            mainFragment.onConnected();
        }
    }

    @Override
    public void onDisonnected(String status) {
        if (mainFragment!=null) {
            mainFragment.onDisonnected();
        }
    }

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        mainFragment = MainFragment();
        //do fragment trasaction
        //get transaction
       transaction.replace(R.id.fragment_container, mainFragment ); transaction.commit();

}
}

You can try the following,

public class SomeClass implements IStatusChangeListener,Parcelable {
  // implement the required methods
}

Activity class

SomeClass someclass = new SomeClass();

intent.putExtra("someclass",someclass)

Reciever Class

    @Override
    public void onReceive(Context context, Intent intent) {
        Bundel b = intent..getExtras()

        if(b != null){
         SomeClass someclass = b.getParcelable("someclass");

        //rest of your logic
       }
    }

Edit:

just put the instance of the SomeClass in the intent which you will be wrapping with a PendingIntent and you can use the intent and the rest of the logic remains same and by this way your MainActivity need not to implement IStatusChangeListener

After searching for hours for the appropriate way to implement such a solution to this problem, I've found a way finally.

In this way, a setListener() method is exposed so that Fragment or Activity can set the listener by sending an instance of IStatusChangeListener .

public class StatusChangeReceiver extends BroadcastReceiver {
    private IStatusChangeListener listener;

    public void setListener(IStatusChangeListener listener) {
        this.listener = listener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        if (NetworkUtil.isNetworkConnected()) {
            listener.onConnected();
        } else {
            listener.onDisconnected();
        }
    }
}

This is the interface:

public interface IStatusChangeListener {
    void onConnected(String status);
    void onDisonnected(String status);
}

Now, it is required to have an instance of IStatusChangeListener interface instead of implementing the IStatusChangeListener interface. And then, pass this instance of IStatusChangeListener to setListener() method.

public class MainFragment extends Fragment { //Not implementing the interface

    private IStatusChangeListener listener = new IStatusChangeListener() {
        @Override
        void onConnected(String status) {
            //some log here
        }

        @Override
        void onDisonnected(String status) {
            //some log here
        }
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        StatusChangeReceiver r = new StatusChangeReceiver();
        r.setListener(listener); // pass the IStatusChangeListener instance
        LocalBroadcastManager.getInstance(getContext()).registerReceiver(r, new IntentFilter("connectionStatus"));
    }
}

Note: Always use LocalBroadcastManager if you register BroadcastReceiver from Fragment .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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