简体   繁体   English

尝试将字符串数组从一个类传递到另一个类时出现NullPointerException

[英]NullPointerException when attempting to pass string array from one class to another

In my Android app, there are some strings that I need to use in two different places in my app. 在我的Android应用中,我需要在我的应用中的两个不同位置使用一些字符串。 So I wrote a class from which I can get these strings. 所以我写了一个类,我可以从中获取这些字符串。 When I try to call the return method from the class that returns the string array, the app crashes with java.lang.NullPointerException . 当我尝试从返回字符串数组的类调用return方法时,应用程序崩溃了java.lang.NullPointerException Here is the class with the return method: 这是带有return方法的类:

public class MetaDataFetcher {

    String[] metaData;

    public String[] getMetaData() {
        //Gets the metadata strings from HarvasterAsync
        try {
            metaData = new HarvesterAsync().execute("urlhere").get();



        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
        return metaData;
    }
}

I am attempting to retrieve the string array like this: 我试图像这样检索字符串数组:

public void updateMetaData(){
//Gets the metadata strings from MetaDataFetcher

String[] receivedMetaData = metaDataFetcher.getMetaData(); 

//More code below...

The NullPointerException occurs at the line String[] receivedMetaData = metaDataFetcher.getMetaData(); NullPointerException发生在String[] receivedMetaData = metaDataFetcher.getMetaData(); .

What am I doing wrong? 我究竟做错了什么?

Edit: 编辑:

I initialize the MetaDataFetcher class with the line MetaDataFetcher metaDataFetcher; 我使用MetaDataFetcher metaDataFetcher;行初始化MetaDataFetcherMetaDataFetcher metaDataFetcher; above the onCreate method in my MainActivity class. 在我的MainActivity类中的onCreate方法之上。

HarvesterAsync is an AsyncTask . HarvesterAsync是一个AsyncTask You can see it here . 你可以在这里看到它。

The problem is concurrency. 问题是并发性。 AsyncTask is non-blocking. AsyncTask是非阻塞的。 So basically this 所以基本上这个

String[] receivedMetaData = metaDataFetcher.getMetaData(); 

will immediately return the receivedMetaData from MetaDataFetcher's field not the result of HarvesterAsync. 将立即从MetaDataFetcher的字段返回receivedMetaData,而不是HarvesterAsync的结果。

In these sort of situations you need to make use of callbacks . 在这种情况下,您需要使用回调 You cannot call execute() of an AsyncTask and right away start using the value returned because the AsyncTask runs on a separate thread and you will have the problem of concurrency as mentioned by @inmyth as well as others in the comments. 您不能调用AsyncTask execute()并立即开始使用返回的值,因为AsyncTask在单独的线程上运行,并且您将遇到@inmyth以及注释中的其他人提到的并发问题。

So what you need to do in-order to make it work is use callbacks. 因此,为了使其工作,您需要做的是使用回调。 At the beginning this might look like a far-fetched solution but trust me it pays off when you are trying to implement large projects. 在开始时,这可能看起来像一个牵强附会的解决方案,但相信我,当你试图实施大型项目时它会得到回报。

First off, declare a listener interface inside your HarvesterAsync class and you can implement these listeners wherever you want to get the value from the AsncTask 首先,在HarvesterAsync类中声明一个监听器接口,你可以在任何想要从AsncTask获取值的地方实现这些监听AsncTask

Here is a sample: 这是一个示例:

public class HarvesterAsync extends AsyncTask<...> {
    // declare your variables
    private List<HarvesterAsyncListener> harvestListeners;

    public HarvesterAsync() {
        // initialise all variables
        harvestListeners = new ArrayList<HarvestAsyncListener>();
    }

    @Override
    protected void doInBackground() {
        // ...
        // fetch your data from somewhere and load it into say "metaData"
        String[] metaData = fetchYourData();

        // notify all listeners that the data has been successfully fetched
        for(listener: harvestListeners) {
            // pass in your result to the method of the interface
            listener.onFetchComplete(metaData);
        }
    }

    // use this method to add new listeners to harvestListeners
    public void addListener(HarvestListener listener) {
        harvestListeners.add(listener);
    }

    public interface HarvestAsyncListener {
        public void onFetchComplete(String[] metaData);
    }
}

Now to obtain the result you can implement the listener interface like this: 现在要获得结果,您可以像这样实现侦听器接口:

public class MetaDataFetcher implements HarvesterAsync.HarvesterAsyncListener {

    String[] metaData;

    public void getMetaData() {
        // initailize the AsyncTask
        HarvestAsync harvestAsnc = new HarvestAsync();

        // add the listener
        harvestAsync.addListener(this);

        ...

    }

    @Override
    public void onFetchComplete(String[] metaData) {
        // do whatever you want with metaData.
        this.metaData = metaData;
        ....
    }

}

You could of course change the method signature in the interface to suit your requirements. 您当然可以更改界面中的方法签名以满足您的要求。

Here you don't need to return the metaData because once it is loaded by the AsyncTask , the AsyncTask does a callback to the onFetchComplete . 在这里,您不需要返回metaData因为一旦AsyncTask加载了它, AsyncTask就会对onFetchComplete进行回调。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM