Android如何绑定Service并在MainActivity的onResume前从Service获取数据
解决方案
- 首先调整
bindService的调用位置:将绑定逻辑从onCreate迁移到onStart方法中,同时在onStop中添加对应解绑逻辑,符合Android生命周期配对规范,避免内存泄漏。 - 适配异步绑定特性:
bindService本身是异步调用,onServiceConnected回调不会在onResume执行前同步触发,无法保证onResume执行时Service已经绑定完成,因此需要将依赖Service数据的逻辑抽为独立方法,分别在绑定成功回调、onResume中按需触发。 - Service侧逻辑优化:当前
ConenctTimezoneDb方法运行在主线程,后续实际发起网络请求时需要开启子线程执行,避免触发ANR,可通过自定义回调接口将请求结果回传给Activity。
修改后的核心代码示例
MainActivity 调整
public class MainActivity extends AppCompatActivity{ ArrayList<City> selected_cities; ArrayList<City> cities; RecyclerView Rview; CitySelectedListAdapter adapter; final int REQUEST_CODE = 1; ICityDao dao; TimezoneService timezoneService ; boolean bound = false; private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { timezoneService = ((TimezoneService.LocalBinder ) service).getService(); Log.d("Service connected","Service Connected "); bound = true; // 绑定成功立刻加载数据更新UI loadDataAndUpdateUI(); } @Override public void onServiceDisconnected(ComponentName name) { bound = false; } } ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); dao = new CItyDao(this); selected_cities = new ArrayList<City>(); showMessage("Created"); create_City_list(); Log.d("created","activity created "); } @Override protected void onStart() { super.onStart(); // 可见时绑定服务 Intent intent = new Intent(this,TimezoneService.class); bindService(intent,connection,Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); // 不可见时解绑服务,避免泄漏 if (bound) { unbindService(connection); bound = false; } } @Override public void onResume() { super.onResume(); showMessage("Resumed"); Log.d("Resume","resume "); // 若已经绑定完成,直接加载数据 if (bound) { loadDataAndUpdateUI(); } } // 抽离依赖Service数据的UI逻辑为独立方法 private void loadDataAndUpdateUI() { if (!bound || timezoneService == null) return; // 可在此调用Service的方法获取时区数据 // timezoneService.ConenctTimezoneDb(自定义回调接收数据) selected_cities = cities.get(0).load(dao); if(selected_cities.size()!=0) { CreateListView(); } for (int i =0;i< selected_cities.size();i++) { load_checkbox(selected_cities.get(i).getName()); } } }
TimezoneService 调整(网络请求加回调示例)
public class TimezoneService extends Service { private final IBinder binder = new LocalBinder(); @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return START_NOT_STICKY; } @Nullable @Override public IBinder onBind(Intent intent) { Log.d("Onbind","onBind "); return binder; } public class LocalBinder extends Binder { public TimezoneService getService() { return TimezoneService.this; } } // 自定义回调接口回传数据 public interface OnTimezoneDataLoadListener { void onLoadSuccess(String data); void onLoadFailed(Exception e); } public void ConenctTimezoneDb(OnTimezoneDataLoadListener listener) { Log.d("connect timezone","connected with time zone db"); // 网络请求开子线程执行 new Thread(() -> { try { URL url = new URL("http://api.timezonedb.com/v2.1/list-time-zone?&format=xml&country=US"); // 此处补充网络请求逻辑,拿到返回数据 String result = 你的网络请求方法(url); // 切回主线程回调结果 new Handler(Looper.getMainLooper()).post(() -> listener.onLoadSuccess(result)); } catch (Exception e) { e.printStackTrace(); new Handler(Looper.getMainLooper()).post(() -> listener.onLoadFailed(e)); } }).start(); } }
内容的提问来源于stack exchange,提问作者Hizafa
相关产品推荐
相关产品推荐

