如何多次使用同一个片段?
Posted
技术标签:
【中文标题】如何多次使用同一个片段?【英文标题】:How to use the same fragment more than once? 【发布时间】:2017-02-15 23:00:40 【问题描述】:我正在创建一个应用程序,该应用程序从网站的 XML 文件中获取数据并将这些数据传递给 Fragment
。
我使用的是 Action Bar
,我有 3 个标签,还有 ViewPager
。
该片段包含一个ListView
,我使用Bundle
传递数据,我可以正确地从片段中获取传递的数据。
public Fragment getItem(int i)
switch(i)
case 0:
Bundle b1= new Bundle();
b1.putString("cat", "artufonews");
Fragment f1 = new LoadFrag();
f1.setArguments(b1);
return f1;
case 1:
Bundle b2 = new Bundle();
b2.putString("cat", "artufo");
Fragment f2 = new LoadFrag();
f2.setArguments(b2);
return f2;
case 2:
Bundle b3 = new Bundle();
b3.putString("cat", "artmyst");
Fragment f3 = new LoadFrag();
f3.setArguments(b3);
return f3;
default :
return new LoadMee();
LoadFrag 是我拥有的片段。我可以正确地传递数据,但是当我尝试使用mPager.getAdapter().notifyDataSetChanged()
更新列表视图时,无论我做什么,这三个选项卡都会向我显示相同的列表。
下面的代码是片段代码:
public static class LoadFrag extends Fragment
String cat;
boolean kl = false;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
//new TestAsync().execute();
View rootView = inflater.inflate(R.layout.listfrage, container, false);
ListView viewer;
String[] hell = (String[])list.toArray(new String[list.size()]);
final String[] tots = (String[])links.toArray(new String[links.size()]);
cat = getArguments().getString("cat");
CustomLister lister = new CustomLister(getActivity(), hell, bmps);
viewer = (ListView)rootView.findViewById(R.id.lister);
viewer.setAdapter(lister);
viewer.setOnItemClickListener(new AdapterView.OnItemClickListener()
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
Toast.makeText(getActivity(), "You clicked: item " + tots[position], Toast.LENGTH_SHORT).show();;
Intent i = new Intent(getActivity(), Starter.class);
i.putExtra("link", tots[position]);
startActivity(i);
);
return rootView;
@Override
public void setMenuVisibility(final boolean visible)
super.setMenuVisibility(visible);
if (visible && kl == false)
getActivity().setTitle(cat);
new TestAsync().execute();
kl = true;
class TestAsync extends AsyncTask<Void, Integer, String>
String TAG = getClass().getSimpleName();
ProgressDialog dialog;
protected void onPreExecute ()
Log.d(TAG + " PreExceute","On pre Exceute......");
dialog = new ProgressDialog(getActivity());
dialog.setMessage("Loading content..");
dialog.setIndeterminate(true);
dialog.setCancelable(false);
dialog.show();
protected String doInBackground(Void...arg0)
Log.d(TAG + " DoINBackGround","On doInBackground...");
tasker(cat);
return "You are at PostExecute";
protected void onProgressUpdate(Integer...a)
Log.d(TAG + " onProgressUpdate", "You are in progress update ... " + a[0]);
protected void onPostExecute(String result)
Log.d(TAG + " onPostExecute", "" + result);
dialog.dismiss();
mPager.getAdapter().notifyDataSetChanged();
public void tasker(String tag)
try
URL url = new URL("http://www.skyovnis.com/test.xml");
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(new InputSource(url.openStream()));
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getElementsByTagName(tag);
for (int i = 0; i < nodeList.getLength(); i++)
Node node = nodeList.item(i);
Element fstElmnt = (Element) node;
NodeList nameList = fstElmnt.getElementsByTagName("title");
Element nameElement = (Element) nameList.item(0);
nameList = nameElement.getChildNodes();
list.add(((Node)nameList.item(0)).getNodeValue());
NodeList websiteList = fstElmnt.getElementsByTagName("link");
Element websiteElement = (Element) websiteList.item(0);
websiteList = websiteElement.getChildNodes();
links.add(((Node) websiteList.item(0)).getNodeValue());
NodeList imgLinks = fstElmnt.getElementsByTagName("linkp");
Element imgElement = (Element) imgLinks.item(0);
imgLinks = imgElement.getChildNodes();
linksp.add(((Node) imgLinks.item(0)).getNodeValue());
bmps = new Bitmap[linksp.size()];
String[] imgs = (String[])linksp.toArray(new String[linksp.size()]);
for(int i = 0; i < linksp.size(); i++)
URL urls = new URL(imgs[i]);
bmps[i] = BitmapFactory.decodeStream(urls.openConnection().getInputStream());
org.jsoup.nodes.Document docs = Jsoup.connect("http://www.skyovnis.com/arecibo-message/").get();
org.jsoup.select.Elements newsHeadlines = docs.select("div.entry-content p");
for(org.jsoup.nodes.Element ele : newsHeadlines)
hello = hello + ele.text();
catch(Exception e)
System.out.println(e);
基本上,根据我传递的数据,AsyncTask
将运行并从 xml 文件中读取。我传递给片段的字符串是从 xml 中查找的标记。一切正常,除了每个标签都显示相同的列表。
我在这里做错了什么?
编辑
ViewPager 适配器:
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.setOnPageChangeListener(
new ViewPager.SimpleOnPageChangeListener()
@Override
public void onPageSelected(int position)
// When swiping between pages, select the
// corresponding tab.
getActionBar().setSelectedNavigationItem(position);
);
我的 CustomLister 类,
package com.ovnis.skybeings;
import java.net.URL;
import java.util.List;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class CustomLister extends ArrayAdapter<String>
private final Activity context;
private final String[] web;
private final Bitmap[] bmps;
public CustomLister(Activity context, String[] web, Bitmap[] bmps)
super(context, R.layout.list_compon, web);
this.context = context;
this.web = web;
this.bmps = bmps;
@Override
public View getView(int pos, View view, ViewGroup parent)
LayoutInflater inflater = context.getLayoutInflater();
View rowView = inflater.inflate(R.layout.list_compon, null, true);
TextView txtTitle = (TextView)rowView.findViewById(R.id.txt);
ImageView imageView = (ImageView)rowView.findViewById(R.id.img);
txtTitle.setText(web[pos]);
imageView.setImageBitmap(bmps[pos]);
return rowView;
我的适配器,
public static class MyAdapter extends FragmentPagerAdapter
public MyAdapter(FragmentManager fm)
super(fm);
@Override
public int getCount()
return tabs.length;
@Override
public Fragment getItem(int i)
switch(i)
case 0:
return new LoadMee();
case 1:
return new LoadFrag().newInstance("artufonews");
case 2:
return new LoadFrag().newInstance("artifos");
default :
return new LoadMee();
@Override
public int getItemPosition(Object object)
return POSITION_NONE;
【问题讨论】:
那是因为你没有收到之前发送的包。 @ישואוהבאותך 不,那不可能。你能看到我的 setMenuVisibility 代码吗?每当我选择选项卡时,它都会将我的应用程序标题设置为传递给片段的字符串。它也可以正常工作,它也改变了我的标题。唯一的问题是所有标签显示我是同一个列表 好吧,我错了。我以前没有看到你的cat = getArguments().getString("cat");
。可能是因为您没有将CustomLister lister = new CustomLister(getActivity(), hell, bmps);
设置为您的类别?
您好,您可以显示ViewPager
的适配器的代码吗?
您仍然没有显示您的ViewPager
的适配器代码。我需要看看你的MyAdapter
课程。您正在调用 mPager.getAdapter().notifyDataSetChanged();
以通知 MyAdapter
数据集已更改。单独通知MyAdapter
不会神奇地改变您的观点。我需要知道你是如何实现MyAdapter
。
【参考方案1】:
您需要捕获您之前发送的Bundle
。执行以下操作可能可以解决您的问题:
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState)
super.onActivityCreated(savedInstanceState);
Bundle bundle = this.getArguments();
if (bundle != null)
yourStringData= bundle.getString("cat", "DEFAULT_VALUE");
setupYourUIWithTheData(yourStringData);
else
Log.d(TAG, "bundle null");
private void setupYourUIWithTheData(String yourData)
// Process the received data here.
// Show all related with the data here.
--- 更新 ---
要将值传递给Fragment
,推荐的方法是向您的Fragment
添加静态方法,例如:
public static LoadFrag newInstance(String category)
LoadFrag fragment = new LoadFrag ();
Bundle bundle = new Bundle();
bundle.putString("cat", category);
fragment.setArguments(bundle);
return fragment;
那么你可以简单地调用它:
LoadFrag.newInstance("your_category");
【讨论】:
我现在试试这个 我不明白如何将Fragment
重构为使用newInstance()
可以帮助解决问题。
@Egor:好吧,在我添加答案之前,我想念阅读整个代码。认为 op 还没有实现读取 Bundle。我很抱歉。
不,它也不起作用。我的列表视图在两个 3 个标签中仍然有相同的项目
@ישואוהבאותך 我尝试了您编辑的答案,但无效。【参考方案2】:
出了什么问题:
在您的MyAdapter
的getItemPosition()
方法中,您将返回POSITION_NONE
。这意味着每当您调用MyAdapter#notifyDataSetChanged()
时,您将重新创建ViewPager
中的所有片段。您可以通过在 LoadFrag#onCreateView()
中添加日志消息来验证此行为。
public static class LoadFrag extends Fragment
...
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
// Add a Log message here to verify
Log.d("LoadFrag", "In onCreateView");
...
...
请注意,在您的 AsyncTask
完成后,每次都会调用 onCreateView()
。在您的AsyncTask
完成并显示您的ListView
的初始状态后,您基本上是在重新创建LoadFrag
。
如何解决
在您的CustomLister
中添加一个方法来更新您的数据。
public class CustomLister extends ArrayAdapter<String>
...
public void updateData(String[] newWeb, Bitmap[] newBmps)
web = newWeb;
bmps = newBmps;
notifyDataSetChanged();
...
在您的AsyncTask
中,获取您的CustomLister
的引用并使用新数据集调用lister.updateData()
,而不是调用mPager.getAdapter().notifyDataSetChanged()
,
【讨论】:
这也没有解决我的问题,感谢您的更正。以上是关于如何多次使用同一个片段?的主要内容,如果未能解决你的问题,请参考以下文章