Android将数组的值从异步任务传递到另一个类

时间:2016-05-23 11:44:52

标签: android arrays android-asynctask global-variables

我试图从一个异步任务类获取一个数组到另一个片段类但我得到一个空指针异常。我在这里看到了许多答案,但我没有看到实际回答过这个问题。

我尝试从异步类任务返回值,我试图使数组静态但我没有成功。

这些是类(我已经突出显示了我试图从中获取值并将其带到的位置):

    public class DemoPreviewSongFragment extends DemoFragmentBase {
        // The DynamoDB object mapper for accessing DynamoDB.
       private final DynamoDBMapper mapper;
        public DemoPreviewSongFragment() {
            mapper = AWSMobileClient.defaultMobileClient().getDynamoDBMapper();
        }

        SongPreviewCardsDataAdapter mCardAdapter;
        com.wenchao.cardstack.CardStack mCardStack;

        @Override
        public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
                                 final Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.fragment_preview_song, container, false);
            mCardStack = (CardStack)view.findViewById(R.id.cardstackcontainer);
            mCardStack.setContentResource(R.layout.song_preview_card_layout);
            mCardStack.setStackMargin(20);

            new getSongsInCategory().execute();

/////////// WHEN TRYING TO REFERENCE THE STATIC ARRAY RESULT HERE I GET A NULL /////////// POINTER. I NEED THE ARRAY HERE SO I CAN PUT IT IN THE ADAPTER.   

            mCardAdapter = new SongPreviewCardsDataAdapter(getActivity().getApplicationContext(),0);
            mCardAdapter.add("test1");

            mCardStack.setAdapter(mCardAdapter);

            return view;
        }



//////////////////// THIS IS THE ARRAY I AM TRYING TO PASS /////////////////////
        public static PaginatedQueryList<SongDatabaseMappingAdapter> result;

        public class getSongsInCategory extends AsyncTask {

            @Override
            protected Object doInBackground(Object[] params) {

                SongDatabaseMappingAdapter songs = new SongDatabaseMappingAdapter();
                songs.setCategory("Rap");

                String userRatingQueryString = "5";

                Condition rangeKeyCondition = new Condition()
                        .withComparisonOperator(ComparisonOperator.EQ)
                        .withAttributeValueList(new AttributeValue().withN(userRatingQueryString));

                DynamoDBQueryExpression queryExpression = new DynamoDBQueryExpression()
                        .withHashKeyValues(songs)
                        .withIndexName("Category-UserRating-index")
                        .withRangeKeyCondition("UserRating", rangeKeyCondition)
                        .withConsistentRead(false);

                result = mapper.query(SongDatabaseMappingAdapter.class, queryExpression);
                return result;
            }
    }

我不确定我在做错了什么,为什么它应该是一个全局(静态)数组的空指针?有没有更好的方法来做到这一点?

感谢您的帮助

3 个答案:

答案 0 :(得分:2)

在AsynTask的onPostexecute()方法中将数据设置为适配器。您正在获得异常,因为您没有获得任何数据是适配器。 AsynTask在后台执行操作,可能是在AsyncTask完成之前使用值的情况。所以在onPostExecute中设置适配器。

doInBackground(){
}
onPostExecute(){

// use result array here and set it on adapter
}

答案 1 :(得分:1)

Asynctask是异步的,因此数组为null。您可以通过访问OnPostExecute()方法在asynctask完成时更新适配器。

这是我现在改变了逻辑的代码。

public class DemoPreviewSongFragment extends DemoFragmentBase {
    // The DynamoDB object mapper for accessing DynamoDB.
   private final DynamoDBMapper mapper;
    public DemoPreviewSongFragment() {
        mapper = AWSMobileClient.defaultMobileClient().getDynamoDBMapper();
    }

    SongPreviewCardsDataAdapter mCardAdapter;
    com.wenchao.cardstack.CardStack mCardStack;

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
                             final Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_preview_song, container, false);
        mCardStack = (CardStack)view.findViewById(R.id.cardstackcontainer);
        mCardStack.setContentResource(R.layout.song_preview_card_layout);
        mCardStack.setStackMargin(20);

        new getSongsInCategory().execute();

        return view;
    }

    public class getSongsInCategory extends AsyncTask {

        @Override
        protected Object doInBackground(Object[] params) {

            SongDatabaseMappingAdapter songs = new SongDatabaseMappingAdapter();
            songs.setCategory("Rap");

            String userRatingQueryString = "5";

            Condition rangeKeyCondition = new Condition()
                    .withComparisonOperator(ComparisonOperator.EQ)
                    .withAttributeValueList(new AttributeValue().withN(userRatingQueryString));

            DynamoDBQueryExpression queryExpression = new DynamoDBQueryExpression()
                    .withHashKeyValues(songs)
                    .withIndexName("Category-UserRating-index")
                    .withRangeKeyCondition("UserRating", rangeKeyCondition)
                    .withConsistentRead(false);

        return mapper.query(SongDatabaseMappingAdapter.class, queryExpression);

        }

      @Override
      public void onPostExecute(Object obj){

        //Here array will not be null.

       PaginatedQueryList<SongDatabaseMappingAdapter> result=(PaginatedQueryList<SongDatabaseMappingAdapter>)obj;
         mCardAdapter = new SongPreviewCardsDataAdapter(getActivity().getApplicationContext(),result[0]);
        mCardAdapter.add("test1");

        mCardStack.setAdapter(mCardAdapter);

        }

    }

答案 2 :(得分:1)

好的,所以你必须要理解AsyncTask的原理,简单地说,它在不同的线程上运行一些东西,而不是阻塞当前线程,并且通过不阻塞意味着它将自动转到下一行在调用execute之后,不依赖于asynk任务中的任务持续时间而不是等待任务完成。

在你的情况下:

new getSongsInCategory().execute(); // here you call the task to generate the result
result.doSomething() // this line will be called before your task is completed, so the result won't be initialized => NPE

你应该这样做的方法是使用Observer模式(回调)。您将一个观察者设置为您的AsyncTask以查明它何时完成。完成后,它将通知观察任务的对象。

所以一个例子可能是这样的:

public class DemoPreviewSongFragment extends DemoFragmentBase implements AwesomeObserver {
 public interface AwesomeObserver {
     void theTaskIsDone(Object theTaskResult);
 }

 public View onCreateView(final LayoutInflater inflater, final ViewGroup container,
                             final Bundle savedInstanceState) {
... 
new GetSongsInCategory(this).execute();

//新的最佳做法是     new GetSongsInCategory(this).executeOnExecutor(THREAD_POOL_EXECUTOR);  }

@Override
theTaskIsDone(Object theTaskResult) {
    theTaskResult.doSomething();
    //In your case
      mCardAdapter = new SongPreviewCardsDataAdapter(getActivity().getApplicationContext(),0);
        mCardAdapter.add("test1");

        mCardStack.setAdapter(mCardAdapter);
}

public class GetSongsInCategory extends AsyncTask {
  private AwesomeObserver observer;
  public GetSongsInCategory(AwesomeObserver someone) {
      observer = someone;
  }
 // doInBackground ....and do things

 public void onPostExecute(Object object) {
    // at this point you know the task is done
   if(observer != null) 
     observer.theTaskIsDone(object);
    } 
 }

}

现在为避免混淆,theTaskIsDone&amp; onPostExecute只是示例,您可以使用它适用于您的示例。 这实际上是一种通用的方法,您也可以从onPostExecute调用异步任务的包含类中的方法,但是如果您在单独的java文件中有内部异步任务或异步任务,则此方法将起作用