【问题标题】:Updating Activity TextView from service using Service binding使用服务绑定从服务更新 Activity TextView
【发布时间】:2014-05-31 08:59:48
【问题描述】:

我有一项读取 GPS 纬度和经度的服务。我想从服务的locationlisteneronLocationChanged 更新活动。

我怎样才能实现它?我一直在阅读Service Bound,但看起来它只是让活动调用服务中的方法,而不是服务调用活动中的 textView。难道绑定服务是不可能实现的吗?

【问题讨论】:

    标签: android service android-activity textview


    【解决方案1】:

    您应该使用 Service 中的 LocalBroadcastManager 类将 Intent 发送回 Activity。

    例如,包含单个TextViewActivity 可以像这样设置BroadcastReceiver

    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));
        }
    }
    

    一个基本的Service可以广播所有位置变化如下:

    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;
        }
    }
    

    【讨论】:

      【解决方案2】:

      是什么阻止您(在您的服务中)声明这样的方法:

      public void setTextViewToModify(TextView tv);
      

      在您将 TextView 的引用提供给您的 Service 之后,它可以像访问任何其他对象一样访问它。

      另一方面,我不建议这种解决方案,因为这种方式真的很容易造成内存泄漏。此外,TextView 不应离开 Activity 的上下文,因为它是 Activity 的一部分。即使在 Activity 被销毁后,引用仍会保留在 Service 中,我想您可以想象如果 Service 接触到死的 TextView 会发生什么。

      您应该从您的服务广播更新,并使用LocalBroadcastRecever 在您的活动中获取这些更新。这样,TextView 将由负责该操作的人更新,即 Activity 本身。

      如果您不喜欢 LocalBroadcatReceiver 的概念,您可以尝试任何事件总线解决方案。它更易于使用,您可以传递任何类型的对象。您不必使它们可编组(Serializable/Parcelable)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多