Я пытаюсь добавить рабочего Fragment
в мой MainActivity
из добавленного Fragment
. Fragment
реализует DownloadListener
для WebView
он содержит, является добавление рабочего Fragment
когда onDownloadStart()
называется:Добавить фрагмент без интерфейса пользователя к действию из другого фрагмента
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition,
String mimeType, long contentLength) {
getActivity().getSupportFragmentManager().beginTransaction()
.add(new DownloadFragment().newInstance(url, contentDisposition, mimeType), null)
.commit();
}
Но когда я добавить новый Fragment
, он, кажется, застрял в бесконечном цикле, вызывая onCreate
, onCreateView
, onCreateOptionsMenu
и onDownloadStart
в текущем Fragment
. Повторяя эти предупреждения примерно через двадцать вызовов onCreateOptionsMenu()
:
12-10 08:33:36.717 25582-25582/com.example.package W/cr.BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 25582
12-10 08:33:36.732 25582-25582/com.example.package W/art: Attempt to remove non-JNI local reference, dumping thread
12-10 08:33:36.734 25582-25582/com.example.package W/AwContents: onDetachedFromWindow called when already detached. Ignoring
Пока, наконец, не останавливается после запуска из памяти:
12-10 08:33:37.123 25582-25582/com.example.package I/chromium: [INFO:GrGLUtil.cpp(169)] NULL GL version string.
12-10 08:33:37.346 25582-25582/com.example.package W/cr.BindingManager: Cannot call determinedVisibility() - never saw a connection for the pid: 25582
12-10 08:33:37.440 25582-26194/com.example.package E/chromium: [ERROR:gl_in_process_context.cc(208)] Failed to initialize GLES2CmdHelper
12-10 08:33:37.464 25582-25582/com.example.package W/libc: pthread_create failed: could not allocate 1044480-bytes mapped space: Out of memory
12-10 08:33:37.464 25582-25582/com.example.package E/chromium: [ERROR:platform_thread_posix.cc(112)] pthread_create: Try again
12-10 08:33:37.722 25582-25582/com.example.package W/google-breakpad: ### ### ### ### ### ### ### ### ### ### ### ### ###
12-10 08:33:37.722 25582-25582/com.example.package W/google-breakpad: Chrome build fingerprint:
12-10 08:33:37.722 25582-25582/com.example.package W/google-breakpad: 1.9.1
12-10 08:33:37.722 25582-25582/com.example.package W/google-breakpad: 69
12-10 08:33:37.722 25582-25582/com.example.package W/google-breakpad: 45012863-7d3b-4c30-8ccf-e65394c57d85
12-10 08:33:37.722 25582-25582/com.example.package W/google-breakpad: ### ### ### ### ### ### ### ### ### ### ### ### ###
12-10 08:33:37.722 25582-25582/com.example.package A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x0 in tid 25582 (example.package)
Это мой текущий код DownloadFragment
:
public class DownloadFragment extends Fragment {
private static final int REQUEST_CODE_STORAGE = 0;
private static final String KEY_LINK = "link_key";
private static final String KEY_DISPOSITION = "disposition_key";
private static final String KEY_MIME_TYPE = "mime_type_key";
private String mLink;
private String mDisposition;
private String mMimeType;
public WebFragment newInstance(String link, String contentDisposition, String mimeType) {
WebFragment fragment = new WebFragment();
Bundle args = new Bundle();
args.putString(KEY_LINK, link);
args.putString(KEY_DISPOSITION, contentDisposition);
args.putString(KEY_MIME_TYPE, mimeType);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
mLink = getArguments().getString(KEY_LINK);
mDisposition = getArguments().getString(KEY_DISPOSITION);
mMimeType = getArguments().getString(KEY_MIME_TYPE);
if(ContextCompat.checkSelfPermission(getContext(),
Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
if(shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
// TODO: add request permission rationale dialog
Timber.d("Should show request permission rationale");
} requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE_STORAGE);
} else {
downloadFile(mLink, mDisposition, mMimeType);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_STORAGE:
if(grantResults[REQUEST_CODE_STORAGE] == PackageManager.PERMISSION_GRANTED) {
downloadFile(mLink, mDisposition, mMimeType);
} else {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(mLink)));
} break;
}
}
public void downloadFile(String url, String contentDisposition, String mimeType) {
String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType);
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
request.allowScanningByMediaScanner();
DownloadManager manager = (DownloadManager) getContext().getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
getActivity().getSupportFragmentManager().beginTransaction().remove(this).commit();
}
}
Я также попытался добавить метод onCreateView
, переместив весь код с onCreate
там (кроме setRetainInstance
), но это приводит к такому же результату. Я не могу понять, почему он будет повторять предыдущие Fragment
, чего мне не хватает?
Это не то же самое, что добавить 'implements DownloadListener' в мой' MainActivity' и использовать 'mWebView.setDownloadListener (((MainActivity) getActivity())' (вместо 'mWebView.setDownloadListener (this)')? Вместо того, чтобы создавать свой собственный интерфейс, я просто попробовал это с теми же результатами. Я просто обнаружил, что 'onDownloadStart' вызывается несколько раз, прежде чем снова вызвать' onCreate', что тоже кажется странным. – Bryan
Кроме того, Причина, по которой я хотел использовать «DownloadFragment», состояла в том, чтобы я мог вызвать тот же код в разных местах моего приложения. Не обязательно полагаться на мою «MainActivity». Я планировал добавить «BroadcastReceiver» к моему «манифесту» для обработки 'ACTION_DOWNLOAD_COMPLETE', вместо того, чтобы добавлять его к нескольким действиям.И я думал, что' getActivity(). GetSupportFragmentManager() 'свяжет' DownloadFragment' с 'MainActivity', а не «WebFragment». Даже если 'WebFragment' вызывает метод, нет? – Bryan
Если вы настроили свою деятельность как слушателя непосредственно на свой «WebView», вы снова связываете экземпляр действия с представлением, то есть менеджером совершенно другого компонента, и IMHO этого следует избегать. Подумайте о фрагментах как полностью изолированных модулях, которые должны предоставить API для внешнего мира. Таким образом было бы легче проектировать их в соответствии с лучшими принципами. –