2016-04-08 31 views
1

我抬头看了一下互联网,但找不到一个涵盖我的场景的例子。我所试图做的是:如何保持轮询绑定服务?

1)要尽快启动并绑定到一个服务为我的活动开始(完成)

2)然后服务自己绑定到另一个服务寻找从连接设备的用户 输入,并保存一个字符串将一个字符串变量(完成)

3)我想这个字符串发回的活动,所以我可以检查什么 是一个nd根据它进行网络通话。

现在3号)是我的挑战。我设法用Timer运行一秒钟,然后检查写入服务的值,但不知怎的,这似乎并不正确,我认为可能有更成熟的解决方案。但是,我似乎无法弄清楚。

我已经从文档中获取了代码并只添加了计时器。在这个例子中,这只是一个服务,它只是产生一个随机数(这通常会被我的第二个服务取代)。 这是服务的代码:

public class LocalService extends Service { 

    private final IBinder mBinder = new LocalBinder(); 

    private final Random mGenerator = new Random(); 

    public class LocalBinder extends Binder { 
     LocalService getService() { 
      return LocalService.this; 
     } 
    } 

    @Override 
    public IBinder onBind(Intent intent) { 
     return mBinder; 
    } 

    public int getRandomNumber() { 
     return mGenerator.nextInt(100); 
    } 
} 

而且这是在我的活动代码:

public class MainActivity extends AppCompatActivity { 

    LocalService mService; 
    boolean mBound = false; 
    Timer timer; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     timer = new Timer(); 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     Intent intent = new Intent(this, LocalService.class); 
     bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 

     timer.schedule(new MyTimerTask(new Handler(), this), 1000, 1000); // run on every second 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     if (mBound) { 
      unbindService(mConnection); 
      mBound = false; 
     } 

     timer.cancel(); 
     timer.purge(); 
    } 

    private class MyTimerTask extends TimerTask { 
     Handler handler; 
     MainActivity ref; 

     public MyTimerTask(Handler handler, MainActivity ref) { 
      super(); 
      this.handler = handler; 
      this.ref = ref; 
     } 

     @Override 
     public void run() { 
      handler.post(new Runnable() { 
       @Override 
       public void run() { 
        if (mBound) { 
         int num = ref.mService.getRandomNumber(); 
         // just as an example, raise a toast to see if it works 
         // but otherwise the value will be handled 
         Toast.makeText(ref, "number: " + num, Toast.LENGTH_SHORT).show(); 
        } 
       } 
      }); 
     } 
    } 

    private ServiceConnection mConnection = new ServiceConnection() { 

     @Override 
     public void onServiceConnected(ComponentName className, 
             IBinder service) { 
      LocalService.LocalBinder binder = (LocalService.LocalBinder) service; 
      mService = binder.getService(); 
      mBound = true; 
     } 

     @Override 
     public void onServiceDisconnected(ComponentName arg0) { 
      mBound = false; 
     } 
    }; 
} 

我的问题是:这是一个好方法(它的工作原理),或者是坏的,有什么选择?

+0

你有一个绑定的服务这样:

LocalBroadcastManager.getInstance(context).unregisterReceiver(broadcastReceiver); 

现在,当您的服务发送广播,你可以在你的Activity处理它不要使用广播接收器:毕竟你有一个绑定的连接,只需将一个接口对象传递给你的服务,并让服务调用它就可以了 – pskink

+0

@pskink我不知道w你的意思是让服务调用接口对象?你的'LocalService'中的 – Apostrofix

+0

创建一个'register(ISomeInterface)'方法,当你的活动绑定到你的服务(onServiceConnected'内部)时调用'mService.register(MainActivity.this)',当然'MainActivity'必须实现' ISomeInterface',这样,如果你调用'register',你的服务可以将'ISomeInterface'存储在一个私有字段中,稍后调用它的一些方法,如果有几个客户端,你的服务可以使用它们的'List'或者android。 os.RemoteCallbackList'类是为这种情况设计的 – pskink

回答

2

您可以使用LocalBroadcastManager从您Service广播发送到您Activity。例如,在你的Service声明:

public static final String BROADCAST_INTENT = "broadcast_intent"; 
public static final String BROADCAST_VALUE = "broadcast_value"; 

private LocalBroadcastManager broadcastManager; 

public void onCreate() { 
    super.onCreate(); 

    broadcastManager = LocalBroadcastManager.getInstance(this); 
} 

现在,每当你想一个String发送到您的Activity你可以这样做是这样的:

private void sendBroadcast(String value) { 

    Intent intent = new Intent(BROADCAST_INTENT); 
    intent.putExtra(BROADCAST_VALUE, value); 
    broadcastManager.sendBroadcast(intent); 
} 

在你Activity声明BroadcastReceiver

private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { 

    @Override 
    public void onReceive(Context context, Intent intent) { 

     handleIntent(intent); 
    } 
}; 

当您绑定到您的Service时注册接收器:

IntentFilter broadcastIntentFilter = new IntentFilter(); 
broadcastIntentFilter.addAction(StreamService.BROADCAST_INTENT); 
LocalBroadcastManager.getInstance(context).registerReceiver((broadcastReceiver), broadcastIntentFilter); 

和注销你来自哪里,你Service解除绑定:

private void handleIntent(Intent intent) { 

    if (intent.getAction().equals(StreamService.BROADCAST_INTENT)) { 
     String value = intent.getStringExtra(StreamService.BROADCAST_VALUE, "default"); 
    } 
} 
+0

这是一个很好的例子!只有一个问题:是否应该在'onServiceConnected'和'onServiceDisconnected'中完成注册和注销接收器,还是可以在'onStart'和'onStop'中执行? – Apostrofix

+1

'onStop()'和'onStart()'很好! –

2

我想发回这个字符串到活动,所以我可以检查它是什么,并基于它进行网络调用。

使用LocalBroadcastManager,greenrobot的EventBus,Square的Otto或一些其他正在进行的事件总线实现。在更改数据时提起事件。有活动登记与公共汽车了解事件。发生更改时,让活动使用更改的数据。

是一个很好的方法