gpt4 book ai didi

android - 重新启动加载程序调用时出错

转载 作者:太空宇宙 更新时间:2023-11-03 13:31:06 24 4
gpt4 key购买 nike

我有一个将数据加载到列表适配器以显示在屏幕上的 fragment 。当我的应用程序启动时,它会启动一项服务来查找新数据,如果找到, fragment 将需要显示这些数据。目前,我的私有(private)广播接收器实际上是在主要 Activity 上——而不是 fragment 。这对我来说似乎不对,但我看不出如何将通知从广播接收器传递回 fragment ,当它在 fragment 本身上时,我读到的另一个问题是建议这种方法。

使用我在下面发布的代码,当我的广播接收器收到通知并在 fragment 上调用 ​​updateConent 时,我得到了 - 我记录了以下错误:

10-26 20:31:21.328: E/AndroidRuntime(711): FATAL EXCEPTION: main
10-26 20:31:21.328: E/AndroidRuntime(711): java.lang.RuntimeException: Error receiving broadcast Intent { act=updatedata flg=0x10 (has extras) } in com.thedailydigi.dailydigi.Main$1@41458418
10-26 20:31:21.328: E/AndroidRuntime(711): at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:765)
10-26 20:31:21.328: E/AndroidRuntime(711): at android.os.Handler.handleCallback(Handler.java:615)
10-26 20:31:21.328: E/AndroidRuntime(711): at android.os.Handler.dispatchMessage(Handler.java:92)
10-26 20:31:21.328: E/AndroidRuntime(711): at android.os.Looper.loop(Looper.java:137)
10-26 20:31:21.328: E/AndroidRuntime(711): at android.app.ActivityThread.main(ActivityThread.java:4745)
10-26 20:31:21.328: E/AndroidRuntime(711): at java.lang.reflect.Method.invokeNative(Native Method)
10-26 20:31:21.328: E/AndroidRuntime(711): at java.lang.reflect.Method.invoke(Method.java:511)
10-26 20:31:21.328: E/AndroidRuntime(711): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
10-26 20:31:21.328: E/AndroidRuntime(711): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
10-26 20:31:21.328: E/AndroidRuntime(711): at dalvik.system.NativeStart.main(Native Method)
10-26 20:31:21.328: E/AndroidRuntime(711): Caused by: java.lang.IllegalStateException: There is already a listener registered
10-26 20:31:21.328: E/AndroidRuntime(711): at android.support.v4.content.Loader.registerListener(Loader.java:130)
10-26 20:31:21.328: E/AndroidRuntime(711): at android.support.v4.app.LoaderManagerImpl$LoaderInfo.start(LoaderManager.java:260)
10-26 20:31:21.328: E/AndroidRuntime(711): at android.support.v4.app.LoaderManagerImpl.installLoader(LoaderManager.java:510)
10-26 20:31:21.328: E/AndroidRuntime(711): at android.support.v4.app.LoaderManagerImpl.createAndInstallLoader(LoaderManager.java:497)
10-26 20:31:21.328: E/AndroidRuntime(711): at android.support.v4.app.LoaderManagerImpl.restartLoader(LoaderManager.java:643)
10-26 20:31:21.328: E/AndroidRuntime(711): at com.thedailydigi.dailydigi.activity.HorizontalListFragment.updateContent(HorizontalListFragment.java:130)
10-26 20:31:21.328: E/AndroidRuntime(711): at com.thedailydigi.dailydigi.Main$1.onReceive(Main.java:36)
10-26 20:31:21.328: E/AndroidRuntime(711): at android.app.LoadedApk$ReceiverDispatcher$Args.run(LoadedApk.java:755)

我发现“Caused by: java.lang.IllegalStateException: There is already a listener registered”是问题的症结所在,但我没有已注册的监听器?

谁能解释一下a)为什么我目前收到上述错误以及b) 这是否是将附加数据加载到 fragment 中的正确方法?

我的相关类的完整代码如下。感谢您的帮助。

主.java

public class Main extends FragmentActivity   { 

private static final String LOG_TAG = "dd-Main";

private HorizontalListFragment mDailyDigiFragment;

private BroadcastReceiver myReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//TODO go update the UI from the database

int newRecords = intent.getIntExtra(DownloadFeedService.DOWNLOADED,0);
long date = intent.getLongExtra(DownloadFeedService.BEGIN_DATE, DownloadFeedService.NULL_DATE);

Log.d(LOG_TAG, newRecords + " new records downloaded!");

if (intent.getStringExtra(DownloadFeedService.KEY).equals(getString(R.string.daily_digi_short))) {
mDailyDigiFragment.updateContent(newRecords, date);
} else {
//TODO add our other fragments here

}
}
};

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Log.v(LOG_TAG, "Main Activity started");

registerReceiver(myReceiver, new IntentFilter(DownloadFeedService.UPDATEDATA));

setContentView(R.layout.activity_main);

if (savedInstanceState == null) {
//mDailyDigiFragment = HorizontalListFragment.newInstance(getString(R.string.daily_digi_short), 10, R.drawable.banner_dailydigi, true);
mDailyDigiFragment = HorizontalListFragment.newInstance(getString(R.string.daily_digi_short), 10, R.drawable.banner_dailydigi, true);
FragmentTransaction dailyDigiTransaction = getSupportFragmentManager().beginTransaction();
dailyDigiTransaction.add(R.id.dailydigi, mDailyDigiFragment).commit();

//TODO instantiate our other fragments here
/*
Fragment digiShowFragment = HorizontalListFragment.newInstance(getString(R.string.digi_show_short), 10, R.drawable.banner_digishow, true);
FragmentTransaction digiShowTransaction = getSupportFragmentManager().beginTransaction();
digiShowTransaction.add(R.id.digishow, digiShowFragment).commit();*/
}


}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

}

Horizo​​ntalListFragment.java

public class HorizontalListFragment extends Fragment
implements LoaderManager.LoaderCallbacks<ArrayList<RssFeed.Article>> {

private ArticleAdapter adapter ;
private static final String LOG_TAG = "dd-HorizontalListFragment";

private static String MAX_LOAD_KEY = "max";
private static String DATASOURCE_KEY = "key";
private static String IMAGE_SRC_KEY = "image";
private static String SHOW_TEXT_OVERLAY = "showOverlay";

private String mRssFeedKey = "";
private int mDefaultLoad;
private int mImageResource = 0;

//TODO do we want to toggle the overlay on the digishow feed?
private boolean mShowTextOverlay = true;
private HorizontalListView mListView;

ArticleLoader mLoader;

public static HorizontalListFragment newInstance(String key, int max, int img, boolean showOverlay) {
HorizontalListFragment myFragment = new HorizontalListFragment();

Bundle args = new Bundle();
args.putString(DATASOURCE_KEY, key);
args.putInt(MAX_LOAD_KEY, max);
args.putInt(IMAGE_SRC_KEY, img);
args.putBoolean(SHOW_TEXT_OVERLAY, showOverlay);
myFragment.setArguments(args);

return myFragment;

}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

Bundle bundle = this.getArguments();
mRssFeedKey = bundle.getString(DATASOURCE_KEY);
mDefaultLoad = bundle.getInt(MAX_LOAD_KEY, getResources().getInteger(R.integer.default_display_max));
mImageResource = bundle.getInt(IMAGE_SRC_KEY, 0);
mShowTextOverlay = bundle.getBoolean(SHOW_TEXT_OVERLAY, true);
mLoader = new ArticleLoader(getActivity(), mRssFeedKey,mDefaultLoad);

getActivity().getSupportLoaderManager().initLoader(0, null, this);

}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.horizontal_list_section, container, false);

ImageView img = (ImageView) view.findViewById(R.id.Header_Image);
img.setImageResource(mImageResource);

mListView = (HorizontalListView) view.findViewById(R.id.hr_listview);

return view;
}

@Override
public Loader<ArrayList<RssFeed.Article>> onCreateLoader(int arg0, Bundle bundle) {
Log.d(LOG_TAG, "onCreateLoader: find " + mDefaultLoad + " articles from " + mRssFeedKey);
return mLoader;
}

@Override
public void onLoadFinished(Loader<ArrayList<RssFeed.Article>> arg0, ArrayList<RssFeed.Article> result) {
Log.d(LOG_TAG, "onLoadFinished with " + result.size() + " records from " + mRssFeedKey);

//update the listview with the combined results list
if (adapter == null) {
adapter = new ArticleAdapter(this.getActivity(), result,true);
mListView.setAdapter(adapter);
} else {
insertNewArticles(result);
adapter.notifyDataSetChanged();
}


//TODO use these methods to reset the list position ?
//mListView.setSelectionFromTop(currentFirstVisibleItem, 0);
//mListView.getFirstVisiblePosition();

}


@Override
public void onLoaderReset(Loader<ArrayList<RssFeed.Article>> arg0) {
Log.v(LOG_TAG, "onLoaderReset");

// TODO what do we need to do here?


}

public void updateContent(int newRecords , long date) {

if (date == DownloadFeedService.NULL_DATE) {
Log.d(LOG_TAG, "updateContent requesting " + newRecords + " new records.");

//this is when some new recent content has been downloaded
mLoader.setDownloadParameters(newRecords, 0);
getActivity().getSupportLoaderManager().restartLoader(0, null, this);

} else {
//this was probably downloaded cuz we're scrolling near the end
}

}

//both lists should already be sorted in date desc order
private void insertNewArticles(ArrayList<RssFeed.Article> listB) {
//TODO - we need to make sure we only add new entries
int listPosition = 0;
for (Article a : listB ) {
for (int i = listPosition; i < adapter.getCount(); i++) {
Article b = adapter.getItem(i);

//already in the list - skip over it
if (a.getInternalId() == b.getInternalId()) {
listPosition = i+1;
break;
}

//our new item is published after - it shows at the front of the list
if (a.getPublicationDate().before(b.getPublicationDate())) {
adapter.insert(a, i-1);
listPosition = i;
break;
}
}

//when we get to new items that pre-date our current list items, add them at the end
if (listPosition == adapter.getCount()) {
adapter.insert(a, listPosition);
listPosition++;
}
}

}

}

文章加载器.java

public class ArticleLoader extends AsyncTaskLoader<ArrayList<RssFeed.Article>> {

private static final String LOG_TAG = "dd-ArticleLoader";

ArrayList<RssFeed.Article> mArticles;
final String mSource;

int mOffset = 0;
int mDownloadCount;

public ArticleLoader(Context context, String source, int max) {
super(context);
mSource = source;
mDownloadCount = max;
}

public void setDownloadParameters(int count, int offset) {
mOffset = offset;
mDownloadCount = count;
}


/**
* This is where the bulk of our work is done. This function is
* called in a background thread and should generate a new set of
* data to be published by the loader.
*/
@Override public ArrayList<RssFeed.Article> loadInBackground() {
Log.d(LOG_TAG, "loadInBackground: find " + mDownloadCount + " articles from " + mSource);


mArticles = ArticleManager.findArticles(getContext().getContentResolver(), mSource, mDownloadCount, mOffset);
return mArticles;
}

@Override
protected void onStartLoading() {
if(mArticles != null) {
deliverResult(mArticles);
} else {
forceLoad();
}
}
}

最佳答案

这里的问题是,当您在 updateContent() 方法中调用 getActivity().getSupportLoaderManager().restartLoader(0, null, this); 时,它再次调用 onCreateLoader(...)。您的 onCreateLoader(..) 方法然后返回与第一次相同的加载程序。这个加载器已经有一个注册的监听器。

要解决这个问题,你只需要onCreateLoader(..)每次返回一个新的加载器。

更改自:

@Override
public Loader<ArrayList<RssFeed.Article>> onCreateLoader(int arg0, Bundle bundle) {
Log.d(LOG_TAG, "onCreateLoader: find " + mDefaultLoad + " articles from " + mRssFeedKey);
return mLoader;
}

到:

@Override
public Loader<ArrayList<RssFeed.Article>> onCreateLoader(int arg0, Bundle bundle) {
Log.d(LOG_TAG, "onCreateLoader: find " + mDefaultLoad + " articles from " + mRssFeedKey);
return new ArticleLoader(getActivity(), mRssFeedKey,mDefaultLoad);
}

关于android - 重新启动加载程序调用时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13096529/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com