上下文服务竞争条件
Context Service race condition
我的应用程序似乎遇到了竞争条件,我不确定原因。它只在我第一次打开应用程序时发生。根据错误,MainActivity 中的静态变量实例为空,但我在启动服务之前设置了变量。似乎服务在 activity 内的 onCreate 完成之前启动 运行,但我认为这是不可能的。知道发生了什么事吗?
错误信息
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.run(LocationService.java:66)
at java.util.Timer$TimerImpl.run(Timer.java:284)
网络Class
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);
}
主要活动
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));
}
}
}
private static Context mCtx = MainActivity.instance;
这是在加载 class 时初始化的。它采用该字段当时的值,而不是您随后使用它时的值。
这意味着如果在 classloader 加载 NetworkCalls
时它是 null
,它将保持 null
直到它被重新分配。
您需要使用 MainActivity.instance
而不是 mCtx
来获取字段的当前值。
我的应用程序似乎遇到了竞争条件,我不确定原因。它只在我第一次打开应用程序时发生。根据错误,MainActivity 中的静态变量实例为空,但我在启动服务之前设置了变量。似乎服务在 activity 内的 onCreate 完成之前启动 运行,但我认为这是不可能的。知道发生了什么事吗?
错误信息
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.run(LocationService.java:66)
at java.util.Timer$TimerImpl.run(Timer.java:284)
网络Class
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);
}
主要活动
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));
}
}
}
private static Context mCtx = MainActivity.instance;
这是在加载 class 时初始化的。它采用该字段当时的值,而不是您随后使用它时的值。
这意味着如果在 classloader 加载 NetworkCalls
时它是 null
,它将保持 null
直到它被重新分配。
您需要使用 MainActivity.instance
而不是 mCtx
来获取字段的当前值。