【问题标题】:Load only one fragment and replace its content only仅加载一个片段并仅替换其内容
【发布时间】:2016-09-07 19:02:27
【问题描述】:

实际上,我创建了一个包含三个项目的导航抽屉,单击每个项目时,它会转到显示特定类型产品的片段,所以我有一个 Activity,其中每种类型都有三个片段。

如果我想添加另一种产品类型,我将不得不创建它的片段。 所以,我的问题是,是否有任何方法只能制作一个片段,并且每次单击一个项目时,只有片段内的数据被更改/替换,而不是用另一个片段本身替换整个片段?

编辑了我的主要活动:

public class MainActivity extends AppCompatActivity {


Toolbar toolbar;

DrawerLayout drawerLayout;

RecyclerView recyclerView;

String navTitles[];
private NavigationView navigationView;
TypedArray navIcons;

RecyclerViewAdapter recyclerViewAdapter;

ActionBarDrawerToggle drawerToggle;
Fragment[] fFragments = new Fragment[3];

@Override

protected void onCreate(Bundle savedInstanceState) {


    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    //Let's first set up toolbar

    setupToolbar();

    //Initialize Views

    recyclerView = (RecyclerView) findViewById(R.id.recyclerView);

    drawerLayout = (DrawerLayout) findViewById(R.id.drawerMainActivity);


    //Setup Titles and Icons of Navigation Drawer

    navTitles = getResources().getStringArray(R.array.navDrawerItems);

    navIcons = getResources().obtainTypedArray(R.array.navDrawerIcons);

    recyclerViewAdapter = new RecyclerViewAdapter(navTitles, navIcons, this);

    recyclerView.setAdapter(recyclerViewAdapter);


    recyclerViewAdapter.setClickedListener(new RecyclerViewAdapter.ClickListerner() {

        @Override

        public void onItemlistener(int index) {

            updateUIWithIndex(index);

        }

    });


    recyclerView.setLayoutManager(new LinearLayoutManager(this));
    //Finally setup ActionBarDrawerToggle

    setupDrawerToggle();


    //Add the Very First  Fragment to the Container

    updateUIWithIndex(1);


}



// on click update fragment
private void updateUIWithIndex(int index) {


    drawerLayout.closeDrawers();


    FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();

    Fragment fFragment = null;


    if (fFragments[index - 1] == null) {

        switch (index) {

            case 1:

                fFragment = new FirstFragment();

                break;

            case 2:

                fFragment = new SecondFragment();

                break;

            case 3:

                fFragment = new ThirdFragment();

                break;

        }

        fFragments[index - 1] = fFragment;

    } else {

        fFragment = fFragments[index - 1];

    }

    fragmentTransaction.replace(R.id.containerView, fFragment);

    fragmentTransaction.commit();


}


void setupToolbar() {

    toolbar = (Toolbar) findViewById(R.id.toolBar);

    setSupportActionBar(toolbar);

    getSupportActionBar().setDisplayShowHomeEnabled(true);

}


void setupDrawerToggle() {

    drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.app_name, R.string.app_name);

    //This is necessary to change the icon of the Drawer Toggle upon state change.

    drawerToggle.syncState();

}


}   

我的片段:

public class FirstFragment extends Fragment implements ClickListner  {

private final String LOG_TAG = FirstFragment.class.getSimpleName();
private DisplayAdapter recyclerViewAdapter;
private RecyclerView recyclView;
private ArrayList<Products> pProduct = null;

private List<Products> prods = null;
ProductDbHelper pDB;
ProgressDialog mJsonDialog;


public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View myView = inflater.inflate(R.layout.all_products, container, false);
    pDB = new ProductDbHelper(getActivity());
    mJsonDialog = new ProgressDialog(getActivity());
    mJsonDialog.setIndeterminate(true);


    if (pDB.isDataAvailable() == 0) {
        mJsonDialog.setMessage("Parsing JSON feed...");
        mJsonDialog.show();
        getFeed();

    } else {

        new FetchDatabaseTask().execute();
    }


    return myView;
}


@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    recyclView = (RecyclerView) view.findViewById(R.id.RecycleList);


    StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);

    recyclView.setLayoutManager(layoutManager);

    recyclerViewAdapter = new DisplayAdapter(getActivity(), new ArrayList<Products>());
    recyclView.setAdapter(recyclerViewAdapter);
    recyclerViewAdapter.setClickListener(this);


}

@Override
public void itemClicked(View view, Parcelable product) {

    Intent intent = new Intent(getActivity(), DetailActivity.class);
    intent.putExtra("P", product);
    startActivity(intent);

}

public void getFeed() {

    RestInterface interfaces = Client.getClient().create(RestInterface.class);

    Call<List<Products>> call = interfaces.getProductsReport();
    call.enqueue(new Callback<List<Products>>() {

        @Override
        public void onResponse(Call<List<Products>> call, Response<List<Products>> response) {

            prods = response.body();


            for (int i = 0; i < prods.size(); i++) {
                pDB.addShop(prods.get(i));
            }

            new FetchDatabaseTask().execute();

            if (mJsonDialog.isShowing())
                mJsonDialog.dismiss();

        }

        @Override
        public void onFailure(Call<List<Products>> call, Throwable t) {

            Log.e(LOG_TAG, "FFFF" + t.toString());
        }
    });

}


public class FetchDatabaseTask extends AsyncTask<Void, Void, List<Products>> {


    protected void onPreExecute() {
        mJsonDialog.setMessage("Reading from internal storage...");
        mJsonDialog.show();

    }

    @Override
    protected List<Products> doInBackground(Void... voids) {

       // get all the shop's products
        List<Products> lProduct = pDB.getAllShops();

      // in the second fragment , sort the products' price in ascending order
         List<Products> lProduct = pDB.sortShopsAscend();


       // in the third fragment sort the products descendingly 
          List<Products> lProduct = pDB.sortShopsDescend();

        return lProduct;
    }


    protected void onPostExecute(List<Products> shops) {
        super.onPostExecute(shops);
        if (shops != null) {
            if (recyclerViewAdapter != null) {
                recyclerViewAdapter.setData(shops);
            } else {
                pProduct = new ArrayList<>();
                pProduct.addAll(shops);
            }
        }


        if (mJsonDialog.isShowing())
            mJsonDialog.dismiss();
    }
}


}

【问题讨论】:

  • 每个 Fragment 的布局是否完全相同,只是显示的内容不同?
  • 是的,布局是一样的
  • 不一定是重复的,但有一些好主意。基本上与下面的答案相同。 stackoverflow.com/questions/9245408/…

标签: android android-fragments navigation-drawer


【解决方案1】:

MainActivity 类中进行这些更改:

public class MainActivity extends AppCompatActivity {  

Toolbar toolbar;    
DrawerLayout drawerLayout;    
RecyclerView recyclerView;    
String navTitles[];
private NavigationView navigationView;
TypedArray navIcons;    
RecyclerViewAdapter recyclerViewAdapter;    
ActionBarDrawerToggle drawerToggle;<

//If you want to use the first fragment only
FirstFragment fragment = null;
.
.
.
recyclerViewAdapter.setClickedListener(new RecyclerViewAdapter.ClickListerner() {

    @Override

    public void onItemlistener(int index) {
        //Call this method to close the drawer layout or you can simply call the close method here
        updateUIWithIndex(index);

        //Do something depending on the index
        if(index == 0){
            //Call getFeed() for example
            fragment.getFeed();
        }
        else if(index == 1){
            //call another method
        }
    }
});
.
.
.

// on click update fragment
//I don't know if you still need the index in this method
private void updateUIWithIndex(int index) {    
    //Close the drawer Layout anyway
    drawerLayout.closeDrawers();     

    if (fragment == null) {
       FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
       //Create an instance of the FirstFragment
       fragment = new FirstFragment();
       fragmentTransaction.replace(R.id.containerView, fragment);    
       fragmentTransaction.commit();     
    }


}

【讨论】:

  • setArguments 只能在 Fragment 附加到 Activity 之前调用,因此这种方法并不能完全回答如何在以后更改显示的数据
  • Suzy 询问多个导航抽屉项目是否可以导致相同的布局但加载的数据不同,所以我的解决方案是在调用 FragmentManager 之前通过参数发送标签或其他内容。然后,使用onCreateView()方法,可以检索参数,并且数据将根据传递的参数而变化。我不知道我理解的是否清楚:)
  • 对,这会起作用,但前提是每次单击列表项时替换片段并设置新参数。因为 Fragment 以其他方式附加到 Activity,因此再次调用 setArguments 不会做任何事情。
  • 是的,当然,旧片段将被销毁并替换为具有不同参数的相同片段的新实例:)
  • 不错^_^,标记为答案,让和你有同样需求的人,都可以关注这个代码!
【解决方案2】:

您可以简单地将变量传递给Fragment 方法。

完全更新的帖子

在你的情况下:

MainActivity 中将片段设置为字段

private FirstFragment firstFragment;

MainActivityOnCreate 方法中运行此片段

FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
firstFragment = null;
firstFragment = new FirstFragment();
fragmentTransaction.replace(R.id.containerView, firstFragment );
fragmentTransaction.commit();

然后将updateUIWithIndex方法替换为片段方法,这样你就有了:

recyclerViewAdapter.setClickedListener(new RecyclerViewAdapter.ClickListerner() {
    @Override
    public void onItemlistener(int index) {
        firstFragment.getFeed(index)
    }
});

将索引传递给 getFeed:

public void getFeed(int index) {

final int currentIndex = index;

    RestInterface interfaces = Client.getClient().create(RestInterface.class);

Call<List<Products>> call = interfaces.getProductsReport();
call.enqueue(new Callback<List<Products>>() {

    @Override
    public void onResponse(Call<List<Products>> call, Response<List<Products>> response) {
        prods = response.body();
        for (int i = 0; i < prods.size(); i++) {
            pDB.addShop(prods.get(i));
        }
        new FetchDatabaseTask(currentIndex ).execute();
        if (mJsonDialog.isShowing())
            mJsonDialog.dismiss();
    }

    @Override
    public void onFailure(Call<List<Products>> call, Throwable t) {
        Log.e(LOG_TAG, "FFFF" + t.toString());
    }
});

将构造函数添加到FetchDatabaseTask

public class FetchDatabaseTask extends AsyncTask<Void, Void, List<Products>> {

   private int currentIndex = 0;

   FetchDatabaseTask(int index) {
      currentIndex = index;
   }

   //ur others methods here
}

然后你可以在onPreExecute,doInBackgroundonPostExecute这样的方法中做你需要的事情:

protected void onPostExecute(List<Products> shops) {
    super.onPostExecute(shops);

    switch (currentIndex) {
        case 0:
            if (shops != null) {
                if (recyclerViewAdapter != null) {
                    recyclerViewAdapter.setData(shops);
                } else {
                    pProduct = new ArrayList<>();
                    pProduct.addAll(shops);
                }
            }
            if (mJsonDialog.isShowing())
                mJsonDialog.dismiss();
            break;
        case 1:
            //ur SecondFragment code
            break;
        case 2:
            //ur ThirdFragment code
            break;
    }
}

因此,对于每种类型的产品或任何您想要的产品,您只能使用一个片段。

【讨论】:

  • 如果我的片段例如有这些方法,我应该如何通知它来处理 doChanges ? public class MyFragment extends Fragment() { //我的代码 public View onCreateView() public void getDataFromDatabase() public void doChanges(String something) { myTextView.setText(something); } }
  • 问题是关于导航抽屉点击后的更新,对吧?点击抽屉项后你想看到什么?
  • 我将如何在 do 更改中实现我的方法?我仍然没有得到我将如何更新 myFragment 中的数据?
  • 你的 Activity 中有 DrawerItemClickListener 对吧?只需从 Activity 中的 Fragment 调用方法即可。
  • 如果您向我展示更多您的代码,我可以发布更好的示例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-18
  • 1970-01-01
相关资源
最近更新 更多