Updating Activity TextView from service using Service binding

后端 未结 2 1428
生来不讨喜
生来不讨喜 2020-12-24 08:59

I have a service for reading GPS latitude and longitude. I would like to update the activity from the service\'s locationlistener\'s onLocationChanged

相关标签:
2条回答
  • 2020-12-24 09:49

    What stops you from declaring a method like this (in your service):

    public void setTextViewToModify(TextView tv);
    

    After you gave the reference of the TextView to your Service, it can access it just like any other object.

    In the other hand, I do not suggest this solution, because this way it is really easy to cause memory leaks. Also, the TextView should not leave the Activity's context since it is a part of the Activity. The reference would remain in the Service, even after the Activity is destroyed, and I guess you can imagine what would happen if the Service touched the dead TextView.

    You should broadcast the updates from your service, and use a LocalBroadcastRecever to get those updates in your Activity. That way the TextView will be updated by the one who is responsible for that, the Activity itself.

    If you don't like the concept of LocalBroadcatReceiver you can try any of the event bus solutions. It is more easy to use, and you can pass any kind of objects. You do not have to make them marshallable (Serializable/Parcelable).

    • http://square.github.io/otto/
    • https://github.com/greenrobot/EventBus
    0 讨论(0)
  • 2020-12-24 09:54

    You should use the LocalBroadcastManager class from within your Service to send an Intent back to the Activity.

    For Example, An Activity containing a single TextView can set up a BroadcastReceiver like such:

    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            final TextView textView = (TextView) findViewById(R.id.main_activity_text_view);
    
            LocalBroadcastManager.getInstance(this).registerReceiver(
                    new BroadcastReceiver() {
                        @Override
                        public void onReceive(Context context, Intent intent) {
                            double latitude = intent.getDoubleExtra(LocationBroadcastService.EXTRA_LATITUDE, 0);
                            double longitude = intent.getDoubleExtra(LocationBroadcastService.EXTRA_LONGITUDE, 0);
                            textView.setText("Lat: " + latitude + ", Lng: " + longitude);
                        }
                    }, new IntentFilter(LocationBroadcastService.ACTION_LOCATION_BROADCAST)
            );
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            startService(new Intent(this, LocationBroadcastService.class));
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            stopService(new Intent(this, LocationBroadcastService.class));
        }
    }
    

    And a basic Service can broadcast all location changes as follows:

    public class LocationBroadcastService extends Service {
    
        public static final String
                ACTION_LOCATION_BROADCAST = LocationBroadcastService.class.getName() + "LocationBroadcast",
                EXTRA_LATITUDE = "extra_latitude",
                EXTRA_LONGITUDE = "extra_longitude";
    
        private static final int
                MIN_TIME = 2000,
                MIN_DISTANCE = 1;
    
        @Override
        public void onCreate() {
            super.onCreate();
            LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            sendBroadcastMessage(locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER));
            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME, MIN_DISTANCE,
                    new LocationListener() {
                        @Override
                        public void onLocationChanged(Location location) {
                            sendBroadcastMessage(location);
                        }
    
                        @Override
                        public void onStatusChanged(String provider, int status, Bundle extras) {
    
                        }
    
                        @Override
                        public void onProviderEnabled(String provider) {
    
                        }
    
                        @Override
                        public void onProviderDisabled(String provider) {
    
                        }
                    }
            );
        }
    
        private void sendBroadcastMessage(Location location) {
            if (location != null) {
                Intent intent = new Intent(ACTION_LOCATION_BROADCAST);
                intent.putExtra(EXTRA_LATITUDE, location.getLatitude());
                intent.putExtra(EXTRA_LONGITUDE, location.getLongitude());
                LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
            }
        }
    
    
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
    
    0 讨论(0)
提交回复
热议问题