我正在尝试从添加到Fragment
的{{1}}向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
,我错过了什么?
答案 0 :(得分:1)
我建议您使用以下内容 - 不要直接从其他片段进行片段交易。这是一种不好的做法,限制了代码的灵活性和可维护性。此外,它将你的碎片相互耦合,这是你应该避免的。
使用侦听器接口通知托管活动它需要创建无头片段,如下所示:
public class WebViewFragment {
private WebViewFragmentListener mListener;
public void onAttach(Context context) {
if (context instanceof WebViewFragmentListener) {
mListener = (WebViewFragmentListener) context;
} else {
throw new IllegalStateException("Hosting activity doesn't implement the fragment listener interface");
}
}
// rest of fragment logic skipped
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
mListener.onDownloadStart(url, contentDisposition, mimeType);
}
public interface WebViewFragmentListener {
void onDownloadStart(String url, String contentDisposition, String mimeType);
}
}
然后,在您的活动中,您实现WebViewFragmentListener
接口并处理工作片段的创建,并将其添加到onDownloadStart()
方法中的活动中。
public class MainActivity extends AppCompatActivity implements WebViewFragmentListener {
// rest of the activity logic...
@Override
public void onDownloadStart(String url, String contentDisposition, String mimeType) {
final DownloadFragment downloadFragment = DownloadFragment.newInstance(url, contentDisposition, mimeType);
final FragmentManager fm = getSupportFragmentManager();
fm.beginTransaction().add(downloadFragment, DownloadFragment.TAG).commit();
}
}
下载完成后,您可以使用相同的方法通知活动,因此可以删除下载片段。
这种分离将使您的代码更有条理,更易于调试。