2015-10-18 108 views
1

每次尝试从活动调用服务中的函数时,我总是收到相同的错误Unable to start activity ... java.lang.NullPointerException: Attempt to invoke virtual method ... on a null object reference尝试在空对象引用(服务)上调用虚拟方法

错误在下面。

10-18 22:30:46.371 1773-1773/com.example.test I/art: Not late-enabling -Xcheck:jni (already on) 
10-18 22:30:47.054 1773-1785/com.example.test I/art: Background sticky concurrent mark sweep GC freed 2727(238KB) AllocSpace objects, 0(0B) LOS objects, 17% free, 939KB/1135KB, paused 19.920ms total 60.374ms 
10-18 22:30:47.070 1773-1773/com.example.test D/AndroidRuntime: Shutting down VM 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime: FATAL EXCEPTION: main 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime: Process: com.example.test, PID: 1773 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test/com.example.test.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'int com.example.test.MyService.getRandomNumber()' on a null object reference 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.ActivityThread.access$800(ActivityThread.java:144) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.os.Handler.dispatchMessage(Handler.java:102) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.os.Looper.loop(Looper.java:135) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.ActivityThread.main(ActivityThread.java:5221) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at java.lang.reflect.Method.invoke(Native Method) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at java.lang.reflect.Method.invoke(Method.java:372) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime: Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'int com.example.test.MyService.getRandomNumber()' on a null object reference 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at com.example.test.MainActivity.onCreate(MainActivity.java:27) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.Activity.performCreate(Activity.java:5937) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2251) 
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)  
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.ActivityThread.access$800(ActivityThread.java:144)  
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)  
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.os.Handler.dispatchMessage(Handler.java:102)  
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.os.Looper.loop(Looper.java:135)  
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at android.app.ActivityThread.main(ActivityThread.java:5221)  
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at java.lang.reflect.Method.invoke(Native Method)  
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at java.lang.reflect.Method.invoke(Method.java:372)  
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)  
10-18 22:30:47.071 1773-1773/com.example.test E/AndroidRuntime:  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)  
10-18 22:30:58.000 1773-1780/com.example.test W/art: Suspending all threads took: 12.169ms 
10-18 22:31:27.545 1773-1780/com.example.test W/art: Suspending all threads took: 17.580ms 
10-18 22:31:31.555 1773-1780/com.example.test W/art: Suspending all threads took: 18.440ms 
10-18 22:31:39.070 1773-1780/com.example.test W/art: Suspending all threads took: 11.531ms 
10-18 22:31:51.100 1773-1780/com.example.test W/art: Suspending all threads took: 5.540ms 

MainActivity如下。

package com.example.test; 

import android.content.ComponentName; 
import android.content.Context; 
import android.content.Intent; 
import android.content.ServiceConnection; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.support.v7.app.AppCompatActivity; 
import android.widget.Toast; 

public class MainActivity extends AppCompatActivity { 

    MyService mService; 
    boolean mBound = false; 

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

     // Bind this and the service together 
     Intent noiseIntent = new Intent(this, MyService.class); 
     bindService(noiseIntent, mConnection, Context.BIND_AUTO_CREATE); 
     startService(noiseIntent); 

     int num = mService.getRandomNumber(); 
     Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); 
    } 

    /** Defines callbacks for service binding, passed to bindService() */ 
    private ServiceConnection mConnection = new ServiceConnection() { 

     @Override 
     public void onServiceConnected(ComponentName className, IBinder service) { 
      // We've bound to LocalService, cast the IBinder and get LocalService instance 
      MyService.ServiceBinder binder = (MyService.ServiceBinder) service; 
      mService = binder.getService(); 
      mBound = true; 
     } 

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

而MyService位于下方。

package com.example.test; 

import android.app.Service; 
import android.content.Intent; 
import android.os.Binder; 
import android.os.IBinder; 

import java.util.Random; 

public class MyService extends Service { 
    // Binder given to clients 
    private final IBinder mBinder = new ServiceBinder(); 
    // Random number generator 
    private final Random mGenerator = new Random(); 

    /** 
    * Class used for the client Binder. Because we know this service always 
    * runs in the same process as its clients, we don't need to deal with IPC. 
    */ 
    public class ServiceBinder extends Binder { 
     MyService getService() { 
      // Return this instance of LocalService so clients can call public methods 
      return MyService.this; 
     } 
    } 

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

    /** 
    * method for clients 
    */ 
    public int getRandomNumber() { 
     return mGenerator.nextInt(100); 
    } 
} 

我一直坚持这个几个小时,我找不到任何解决方案。任何帮助,将不胜感激。 :D

回答

4

bindService()startService()都是异步的。您的mService对象将是null,直到onServiceConnected()被调用,所以直到那时您才能使用它。

+0

所以通过你所说的,我想重新安排'ServiceConnection'在'onCreate'之前,它给了我同样的错误。但我注意到,如果我改变'公众诠释getRandomNumber(){返回mGenerator.nextInt(100); } to'public static int getRandomNumber(){return 10; }',那么它的工作完美无瑕。但我不希望它是一个静态的。有什么建议么? – user5460708

+1

@ user5460708:在Java编程语言中,事件出现在源文件中的顺序与执行顺序无关。在为'mService'分配一个值后,将'mService.getRandomNumber()'call *移动到* onServiceConnected()'中。 – CommonsWare

+0

我已经将'getRandomNumber()'和'Toast.makeText'移动到'onServiceConnected()'中,并且它在静态的情况下完美运行。但是,当我在类中分配了'mService'并将其更新到'onServiceConnected()'中时,为什么我必须将它移动到那里?它不应该在其他地方起作用吗?如果我需要使用服务外部的函数,例如按钮监听器(当服务中的函数从'onServiceConnected'外调用时),该怎么办? – user5460708

相关问题