2016-07-26 10 views
0

Meine Anwendung scheint eine Race Condition zu erleben und ich bin mir nicht sicher warum. Es passiert nur, wenn ich die Anwendung zum ersten Mal öffne. Entsprechend dem Fehler ist die statische Variableninstanz in MainActivity gleich null, aber ich setze die Variable vor dem Start des Dienstes. Es scheint fast so, als ob der Dienst gestartet wird, bevor der onCreate innerhalb der Aktivität beendet wird, aber ich glaube nicht, dass dies möglich ist. Irgendwelche Ideen was passiert?Context Service Race Condition

Fehlermeldung

E/AndroidRuntime: FATAL EXCEPTION: Timer- 

java.lang.NullPointerException                
at NetworkCalls.getRequestQueue(NetworkCalls.java:42)                
at NetworkCalls.addToRequestQueue(NetworkCalls.java:48)                  
at NetworkCalls.createLocationPost(NetworkCalls.java:72)                 
at StaticMethods.handleWarnings(StaticMethods.java:84)                  
at LocationService.checkInPost(LocationService.java:73)                  
at LocationService$1.run(LocationService.java:66)                  
at java.util.Timer$TimerImpl.run(Timer.java:284) 

Networks Klasse

public class NetworkCalls { 
    private static NetworkCalls singleton; 
    private RequestQueue mRequestQueue; 
    private static Context warningCtx = WarningActivity.instance; 
    private static Context mCtx = MainActivity.instance; 

    private NetworkCalls() { 
    } 

    public static synchronized NetworkCalls getInstance() { 
     if (singleton == null) { 
      singleton = new NetworkCalls(); 
     } 
     return singleton; 
    } 

    private RequestQueue getRequestQueue() { 
     if (mRequestQueue == null) { 

      //Problem here is that mCtx is null 
      if(mCtx == null){ 
       Log.e("Error", "It's FUBAR"); 
      }else { 
       Log.e("Error", "It's Okay"); 
      } 
      mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext()); 
     } 
     return mRequestQueue; 
    } 

    private <T> void addToRequestQueue(Request<T> req) { 
     getRequestQueue().add(req); 
    } 

    public void createLocationPost(LocationData locationData) { 
     String url = "http://httpbin.org/post"; 
     HashMap<String, String> params = new HashMap<>(); 
     params.put("Token", "key"); 

     JsonObjectRequest jsObj = new JsonObjectRequest(url, new JSONObject(params), new Response.Listener<JSONObject>() { 
      @Override 
      public void onResponse(JSONObject response) { 
       try { 
        Log.i("NetworkCalls Successful", response.getJSONObject("json").toString()); 
       } catch (JSONException ex) { 
        Log.i("Parsing response", "Unable to get json string"); 
       } 
       // On Response recieved 
      } 
     }, new Response.ErrorListener() { 
      @Override 
      public void onErrorResponse(VolleyError error) { 
       Log.i("NetworkCalls Error", error.toString()); 
      } 
     }); 
     addToRequestQueue(jsObj); 
    } 

Haupt Akivität

public class MainActivity extends AppCompatActivity { 

public static MainActivity instance = null; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    ColorDrawable colorDrawable = new ColorDrawable(Color.parseColor("#000000")); 
    getSupportActionBar().setBackgroundDrawable(colorDrawable); 
    this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); 


     instance = MainActivity.this; 
      startService(new Intent(getBaseContext(), QueuePostService.class)); 
     } 
    } 
} 

Antwort

1
private static Context mCtx = MainActivity.instance; 

Dies initialisiert wird, wenn die Klasse geladen wird. Es nimmt den Wert des Feldes zu dieser Zeit, nicht wenn Sie es später verwenden.

Das bedeutet, dass, wenn es null, wenn die Klassenlader lädt NetworkCalls, es null bleibt, bis es neu zugewiesen wird.

Sie müssten MainActivity.instance anstelle von mCtx verwenden, um den aktuellen Wert des Felds abzurufen.

+0

Das hat perfekt funktioniert, danke. Ich würde nicht darüber nachdenken, wie der Klassenlader funktionierte und es war nahezu unmöglich, das Problem zu verfolgen. Erspart mir stundenlanges Kopfschlagen! – Ubarjohade

+0

Denken Sie nicht darüber nach, wie der Klassenlader geladen wird: Denken Sie daran, dass Java-Variablen Werte und keine Referenzen sind. Nachfolgende Änderungen der Variablen "referenziert" werden daher nicht in der Variablen "referenzieren" wiedergegeben. –

Verwandte Themen