我试图将一个数组从一个异步任务类获取到另一个片段类,但我得到了一个空指针异常。我在这里看到了很多答案,但没有一个真正回答这个问题。
我尝试从异步类任务返回值,并尝试使数组成为静态的,但没有成功。
这些是类(我已经强调了我试图从哪里获得价值并将其带到哪里):
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;
}
}
我不确定我做错了什么,为什么它是一个空指针,而它应该是一个全局(静态)数组?有更好的方法吗?
感谢您的帮助
在AsynTask的onPostexecute()方法中将数据设置为适配器。您正在获取异常,因为您没有获取适配器的任何数据。AsynTask在后台执行操作,可能是在AsyncTask完成之前使用值的情况。因此在onPostExecute中设置适配器。
doInBackground(){
}
onPostExecute(){
// use result array here and set it on adapter
}
好的,所以你必须理解AsyncTask
的原理,简单地说,它在不同的线程上运行一些东西,不阻塞当前线程,不阻塞意味着它将在你调用execute
后自动转到下一行,而不取决于asink任务中任务的持续时间,也不等待任务完成。
在您的情况下:
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
&onPostExecute
只是示例,您可以使用任何适用于您的示例的方法。这确实是一种通用的方法,您也可以从onPostExecute
调用异步任务的包含类中的方法,但如果您在单独的java文件中有内部异步任务或异步任务,则这种方法会起作用。
Asynctask是异步的,因此数组为null。通过在OnPostExecute()方法中进行访问,可以在异步任务完成时更新适配器。
这是我改变了逻辑的代码,现在它可以工作了。
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);
}
}