如何在空对象引用上修复"void android.widget.TextView.setText(java.lang.CharSequence)"? [英] How can I fix 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference?
问题描述
我是android新手.我目前正在开发一个在地图上显示多个位置的应用,该应用的标记位置取自已经设置的中央数据库,并且我知道该如何解决问题.
I'm new to android. I am currently developing an app that displays multiple locations on a map which has its marker locations taken from a central database that I have already set up and I know is working how can I fix my problem.
这是我的MainActivity.java代码
Here is my code for MainActivity.java
package com.example.defiblocator;
import android.Manifest;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Build;
import android.os.Bundle;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.FragmentActivity;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import org.w3c.dom.Text;
public class MainActivity extends FragmentActivity implements OnMapReadyCallback,
LocationListener,GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
GoogleMap mapAPI;
SupportMapFragment mapFragment;
Location mLastLocation;
Marker mCurrLocationMarker;
GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
public static TextView data;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fetchData process = new fetchData();
process.execute();
mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.mapAPI);
mapFragment.getMapAsync(this);
}
@Override
public void onMapReady(GoogleMap googleMap) {
mapAPI = googleMap;
LatLng fox = new LatLng(52.187907,-0.143284);
mapAPI.addMarker(new MarkerOptions().position(fox).title("test"));
mapAPI.moveCamera(CameraUpdateFactory.newLatLng(fox));
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
buildGoogleApiClient();
mapAPI.setMyLocationEnabled(true);
}
} else {
buildGoogleApiClient();
mapAPI.setMyLocationEnabled(true);
}
}
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
mGoogleApiClient.connect();
}
@Override
public void onConnected(Bundle bundle) {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);
mLocationRequest.setFastestInterval(1000);
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onLocationChanged(Location location) {
mLastLocation = location;
if (mCurrLocationMarker != null) {
mCurrLocationMarker.remove();
}
//Place current location marker
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(latLng);
markerOptions.title("Current Position");
markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE));
mCurrLocationMarker = mapAPI.addMarker(markerOptions);
//move map camera
mapAPI.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mapAPI.animateCamera(CameraUpdateFactory.zoomTo(11));
//stop location updates
if (mGoogleApiClient != null) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
}
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
}
这是我的代码,用于从数据库中获取数据并将其转换为JSON.
And this is my code for fetching the data from the database and converting it into a JSON.
fetchData.java
fetchData.java
package com.example.defiblocator;
import android.os.AsyncTask;
import android.widget.TextView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class fetchData extends AsyncTask <Void,Void,Void>{
String data = "";
String json_url;
String dataParsed = "";
String singleParsed = "";
public Integer x = 0;
@Override
protected void onPreExecute(){
json_url = "http://defiblocator.ml/json_get_data.php";
}
@Override
protected Void doInBackground(Void... voids) {
try {
URL url = new URL(json_url);
HttpURLConnection httpURLConnection = (HttpURLConnection)url.openConnection();
InputStream inputStream = httpURLConnection.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
data = data + line;
while(line != null){
line = bufferedReader.readLine();
}
JSONArray JA = new JSONArray(data);
for(int i =0 ; i <JA.length(); i++){
JSONObject JO = (JSONObject) JA.get(i);
singleParsed = JO.get("name") + "," + JO.get("lat") + "," +JO.get("lng") + ",";
dataParsed = dataParsed + singleParsed ;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException | JSONException e){
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
MainActivity.data.setText(dataParsed);
}
}
当我尝试将转换后的数据发送回名称处理,纬度和经度处理的主要活动时,我的错误仅发生在PostExecute()中.如果有一个比我所要分享的方法更简单的方法,我将使用3个单独的数组来完成此操作,但是如果您能将文本视图更改为字符串并将其从其拆分成多个组成部分,那么将不胜感激,我们将不胜感激.
My error only occurs in PostExecute() when I try and send my converted data back to the main activity fro processing into name, latitude, and longitude. I will do this with 3 separate arrays if there is an easier method than what I have please share but otherwise any help would be greatly appreciated as I believe I can change the text view into a string and split it into its constituent parts from there.
推荐答案
如注释中所述,您需要使用接口来实现回调,以使用异步任务的结果.首先创建一个接口.
As mentioned in the comments, you need to implement a callback using an interface to use the results of an Async Task. First create an interface.
新建-> Jave类->接口-> CallbackInterface .java.定义方法原型.
New -> Jave Class -> Interface -> CallbackInterface .java. Define the method prototypes.
CallbackInterface.java
CallbackInterface.java
public interface CallbackInterface {
public void onSuccess(String callbackData);
public void onFailure();
}
在您的MainActivity中,定义一个实现接口的类.请注意,必须在此处定义方法,并且必须包含使用异步任务结果的代码.MainActivity.java
In your MainActivity, define a class which implements the interface. Note that, the methods must be defined here and must contain the code to make use of the result of your Async Task MainActivity.java
public class MainActivity extends AppCompatActivity {
TextView data;
Button performAsync;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Add this without fail.
data = findViewById(R.id.dataTV);
performAsync = findViewById(R.id.performAsync);
performAsync.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Recreating your "process"
new AsyncTaskClass(new CallbackClass()).execute();
}
});
}
/*Create a class which implements the interface. It is a good practise to have
onSuccess and onFailure methods */
public class CallbackClass implements CallbackInterface {
@Override
public void onSuccess(String callbackData) {
//do your callback functions here. In your case, setting the textview to result of parsed data.
data.setText(callbackData);
}
@Override
public void onFailure() {
}
}
}
最后,在fetchData类中(在我的代码中为AsyncTaskClass),执行异步操作,最后在postExecute中,使用适当的参数调用onSuccess方法.请注意,您应该将该类作为参数传递给fetchData类,并使用构造函数,必须将其分配给接口的实例.AsyncTaskClass.java
Finally, in your fetchData class, (AsyncTaskClass in my code) , do your asynchronous operations and finally in postExecute, call the onSuccess method with appropriate parameters. Note that you should pass the class as a parameter to the fetchData class and using the constructor, you must assign it to the instance of the interface. AsyncTaskClass.java
public class AsyncTaskClass extends AsyncTask {
CallbackInterface callbackInterface;
String dataParsed;
public AsyncTaskClass(CallbackInterface callbackInterface) {
this.callbackInterface = callbackInterface;
}
@Override
protected Object doInBackground(Object[] objects) {
dataParsed = "Processed Data";
return null;
}
@Override
protected void onPreExecute() {
dataParsed = "";
}
@Override
protected void onPostExecute(Object o) {
callbackInterface.onSuccess(dataParsed);
}
}
虽然这看起来太多了,但这是您可以在AsyncTaskClass和使用它的Class之间进行通信的唯一方法.如果您听不懂,请随时提出任何澄清.我在项目中检查了上面的答案,效果很好.
While this may seem too much, this is the only way you can communicate between the AsyncTaskClass and the Class which makes use of it. Feel free to ask for any clarifications in case you can't understand. I checked the above answer in my project and it works perfectly.
这篇关于如何在空对象引用上修复"void android.widget.TextView.setText(java.lang.CharSequence)"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!