Cannot refer to a non-final variable inside an inner class defined in a different method

前端 未结 20 2269
一向
一向 2020-11-21 05:04

Edited: I need to change the values of several variables as they run several times thorugh a timer. I need to keep updating the values with every iteration through the timer

20条回答
  •  遇见更好的自我
    2020-11-21 05:42

    The main concern is whether a variable inside the anonymous class instance can be resolved at run-time. It is not a must to make a variable final as long as it is guaranteed that the variable is inside the run-time scope. For example, please see the two variables _statusMessage and _statusTextView inside updateStatus() method.

    public class WorkerService extends Service {
    
    Worker _worker;
    ExecutorService _executorService;
    ScheduledExecutorService _scheduledStopService;
    
    TextView _statusTextView;
    
    
    @Override
    public void onCreate() {
        _worker = new Worker(this);
        _worker.monitorGpsInBackground();
    
        // To get a thread pool service containing merely one thread
        _executorService = Executors.newSingleThreadExecutor();
    
        // schedule something to run in the future
        _scheduledStopService = Executors.newSingleThreadScheduledExecutor();
    }
    
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
    
        ServiceRunnable runnable = new ServiceRunnable(this, startId);
        _executorService.execute(runnable);
    
        // the return value tells what the OS should
        // do if this service is killed for resource reasons
        // 1. START_STICKY: the OS restarts the service when resources become
        // available by passing a null intent to onStartCommand
        // 2. START_REDELIVER_INTENT: the OS restarts the service when resources
        // become available by passing the last intent that was passed to the
        // service before it was killed to onStartCommand
        // 3. START_NOT_STICKY: just wait for next call to startService, no
        // auto-restart
        return Service.START_NOT_STICKY;
    }
    
    @Override
    public void onDestroy() {
        _worker.stopGpsMonitoring();
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    
    class ServiceRunnable implements Runnable {
    
        WorkerService _theService;
        int _startId;
        String _statusMessage;
    
        public ServiceRunnable(WorkerService theService, int startId) {
            _theService = theService;
            _startId = startId;
        }
    
        @Override
        public void run() {
    
            _statusTextView = MyActivity.getActivityStatusView();
    
            // get most recently available location as a latitude /
            // longtitude
            Location location = _worker.getLocation();
            updateStatus("Starting");
    
            // convert lat/lng to a human-readable address
            String address = _worker.reverseGeocode(location);
            updateStatus("Reverse geocoding");
    
            // Write the location and address out to a file
            _worker.save(location, address, "ResponsiveUx.out");
            updateStatus("Done");
    
            DelayedStopRequest stopRequest = new DelayedStopRequest(_theService, _startId);
    
            // schedule a stopRequest after 10 seconds
            _theService._scheduledStopService.schedule(stopRequest, 10, TimeUnit.SECONDS);
        }
    
        void updateStatus(String message) {
            _statusMessage = message;
    
            if (_statusTextView != null) {
                _statusTextView.post(new Runnable() {
    
                    @Override
                    public void run() {
                        _statusTextView.setText(_statusMessage);
    
                    }
    
                });
            }
        }
    
    }
    

提交回复
热议问题