如何在空对象引用上修复"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?

查看:50
本文介绍了如何在空对象引用上修复"void android.widget.TextView.setText(java.lang.CharSequence)"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆