从服务获取Activity的引用

问题描述 投票:7回答:4

我需要从服务中获取对主Activity的引用。

这是我的设计:

main activity.Java

public class MainActivity extends Activity{
private Intent myIntent;
onCreate(){
 myIntent=new Intent(MainActivity.this, MyService.class);

 btnStart.setOnClickListener(new OnClickListener(){
  public void onClick(View V){
   startService(myIntent);
   });
}}

my service.Java

class MyService extends Service{

 public IBinder onBind(Intent intent) {
  return null;
 }

 onCreate(){
 //Here I need to have a MainActivity reference
 //to pass it to another object
 }
}

我怎样才能做到这一点?

[编辑]

感谢大家的答案!这个应用程序是一个Web服务器,此时只适用于线程,我想使用服务,以使其在后台运行。问题是我有一个负责从资产获取页面的类,要执行此操作,我需要使用此方法:

InputStream iS =myActivity.getAssets().open("www/"+filename); 

此时我的项目只有一个Activity而没有服务,所以我可以直接从它自己传递main活动的引用:

WebServer ws= new DroidWebServer(8080,this);

因此,为了使这个应用程序与服务一起工作,我应该在设计中改变什么?

android android-activity android-intent android-service
4个回答
9
投票

你没有解释为什么你需要这个。但这绝对是糟糕的设计。存储对Activity的引用是你不应该对活动做的第一件事。好吧,你可以,但你必须跟踪Activity生命周期并在调用onDestroy()后释放引用。如果您不这样做,您将收到内存泄漏(例如,配置更改时)。而且,在调用onDestroy()之后,Activity被认为是死的,无论如何都很可能无用。

所以只是不要将引用存储在Service中。描述你需要实现的目标。我相信那里有更好的选择。


UPDATE

好的,所以你实际上并不需要引用Activity。相反,您需要引用Context(在您的情况下应该是ApplicationContext,以便不保留对Activity或任何其他组件的引用)。

假设您有一个处理Web Service请求的单独类:

class WebService 
{   
     private final Context mContext;
     public WebService(Context ctx) 
     {
        //The only context that is safe to keep without tracking its lifetime
        //is application context. Activity context and Service context can expire
        //and we do not want to keep reference to them and prevent 
        //GC from recycling the memory.
        mContext = ctx.getApplicationContext(); 
     }

     public void someFunc(String filename) throws IOException 
     {
         InputStream iS = mContext.getAssets().open("www/"+filename); 
     }
}

现在,您可以从Service(建议用于此类后台任务)创建和使用WebService实例,甚至可以从Activity创建和使用WebService实例(当涉及Web服务调用或长时间后台任务时,这非常棘手。)

Service的一个例子:

class MyService extends Service
{
    WebService mWs;
    @Override
    public void onCreate()
    {
        super.onCreate();
        mWs = new WebService(this);

       //you now can call mWs.someFunc() in separate thread to load data from assets.
    }

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

2
投票

要在您的服务和活动之间进行通信,您应该使用AIDL。有关此链接的更多信息:

编辑:(感谢Renan Malke Stigliani)http://developer.android.com/guide/components/aidl.html


2
投票

除非活动和服务分开,否则AIDL是过度的。

只需将绑定器用于本地服务即可。 (这里有完整的例子:http://developer.android.com/reference/android/app/Service.html

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

0
投票

同意inazaruk的评论。但是,就活动和服务之间的通信而言,您有几个选择 - AIDL(如上所述),Messenger,BroadcastReicever等.Messenger方法类似于AIDL,但不要求您定义接口。你可以从这里开始:

http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html

© www.soinside.com 2019 - 2024. All rights reserved.