如何从所有片段使用工具栏上的SearchView

问题描述 投票:0回答:2

我的应用程序具有导航抽屉以及带有2个菜单项的工具栏。其中一项是SearchView ...

public boolean onCreateOptionsMenu(Menu menu)

方法放置在MainActivity中,并且从我的应用程序的所有片段中都可以明显看到工具栏。为了使SearchView在所有片段中都可用,我一直在使用这种可爱的方法:

public void onPrepareOptionsMenu(@NonNull Menu menu)

该方法基本上存在于我应用的每个片段中,所有搜索逻辑都在所有片段中重复,并且看起来像这样:

public class ChampagneFragment extends Fragment {

private View champagneView;
private RecyclerView champagneList;
private ItemsAdapter itemsAdapter;
private List<NewModel> list;

private DatabaseOpenHelper databaseOpenHelper;


public ChampagneFragment() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    setHasOptionsMenu(true);
    // Inflate the layout for this fragment
    champagneView = inflater.inflate(R.layout.fragment_champagne, container, false);

    champagneList = champagneView.findViewById(R.id.champagneRVList);
    champagneList.setLayoutManager(new LinearLayoutManager(getContext()));

    return champagneView;
}


@Override
public void onStart() {
    super.onStart();

    databaseOpenHelper = new DatabaseOpenHelper(getContext());

    //Check exists database
    File database = getContext().getDatabasePath(DatabaseOpenHelper.DBNAME);
    if(false == database.exists()) {
        databaseOpenHelper.getReadableDatabase();
        //Copy db
        if(copyDatabase(getContext())) {
            Toast.makeText(getContext(), "Copy database success", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getContext(), "Copy data error", Toast.LENGTH_SHORT).show();
            return;
        }

    }
    //Get product list in db when db exists
    list = databaseOpenHelper.getChampagne();
    //Init adapter
    itemsAdapter = new ItemsAdapter(getContext(), list);
    //Set adapter for listview
    champagneList.setAdapter(itemsAdapter);

}

// copy SQLite data
private boolean copyDatabase(Context context) {
    try {

        InputStream inputStream = context.getAssets().open(DatabaseOpenHelper.DBNAME);
        String outFileName = DatabaseOpenHelper.DBLOCATION + DatabaseOpenHelper.DBNAME;
        OutputStream outputStream = new FileOutputStream(outFileName);
        byte[]buff = new byte[1024];
        int length = 0;
        while ((length = inputStream.read(buff)) > 0) {
            outputStream.write(buff, 0, length);
        }
        outputStream.flush();
        outputStream.close();
        Log.w("MainActivity","DB copied");
        return true;
    }catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

 //======================SEARCHING FUNCTIONALITY=========================

//fetching SearchView    
@Override
public void onPrepareOptionsMenu(@NonNull Menu menu) {
    super.onPrepareOptionsMenu(menu);

    MenuItem mSearchMenuItem = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) mSearchMenuItem.getActionView();

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {

            // filtering data
            if (newText != null && TextUtils.getTrimmedLength(newText) > 0) {
                newText = newText.toLowerCase();
                List<NewModel> myList = new ArrayList<>();
                for (NewModel newModel : list) {

                    String title = newModel.getTitle().toLowerCase();
                    String description = newModel.getDescription().toLowerCase();
                    if (title.contains(newText) || description.contains(newText)) {

                        myList.add(newModel);
                        onSerach();
                    }

                }

                itemsAdapter.setFilter(myList);
            }
            else {

                list = databaseOpenHelper.getChampagne();
                itemsAdapter = new ItemsAdapter(getContext(), list);
                champagneList.setAdapter(itemsAdapter);
                itemsAdapter.notifyDataSetChanged();
            }
            return true;
        }
    });
}

//getting data from search table in SQLite
public void onSerach(){

    databaseOpenHelper = new DatabaseOpenHelper(getContext());

    //Check exists database
    File database = getContext().getDatabasePath(DatabaseOpenHelper.DBNAME);
    if(false == database.exists()) {
        databaseOpenHelper.getReadableDatabase();
        //Copy db
        if(copyDatabase(getContext())) {
            Toast.makeText(getContext(), "Copy database success", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getContext(), "Copy data error", Toast.LENGTH_SHORT).show();
            return;
        }

    }
    //Get product list in db when db exists
    list = databaseOpenHelper.getSearch();
    //Init adapter
    itemsAdapter = new ItemsAdapter(getContext(), list);
    //Set adapter for listview
    champagneList.setAdapter(itemsAdapter);
}

}

首先,我尝试过滤数据并将其显示在MainActivty的新列表中,但是后来我无法使用片段中的SearchView ...因此,过了一会儿,我决定采用这种方式。但是以某种方式对我来说,这似乎是一种不好的做法...您怎么看?我该怎么做才能使我没有太多重复的代码行并提高效率?

android sqlite android-fragments
2个回答
0
投票
/***
 * Base class ChampagneBaseFragment extends Fragment
***/   
public abstract class ChampagneBaseFragment extends Fragment{

  // here override any Fragment method that has same code in all childs
  // here put variables used by methods of this class
  // if you want to read or write to this variables in child class 
  // then you have to make them public or protected
  public void onSerach(){
   // your onSearch code that is same in childs
  }

  @Override
  public void onPrepareOptionsMenu(@NonNull Menu menu) {
   // your onPrepareOptionsMenu code that is same in childs
  }
  // other common functions...
}


/***
 * Child class ChampagneFragment extends ChampagneBaseFragment 
***/   
public class ChampagneFragment extends ChampagneBaseFragment {// extends ChampagneBaseFragment 

// here you are using methods of ChampagneBaseFragment 
// you can use them without changing them
// or you can override methods of ChampagneBaseFragment and call super to use them
// then add your code below super call


}

0
投票

实现后,这是我的Fragment类,它继承了BasaFragment类

public class ChampagneFragment extends BaseFragment {

private View champagneView;
private RecyclerView champagneList;
private ItemsAdapter itemsAdapter;
private List<NewModel> list;

private DatabaseOpenHelper databaseOpenHelper;


public ChampagneFragment() {
    // Required empty public constructor
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    setHasOptionsMenu(true);
    // Inflate the layout for this fragment
    champagneView = inflater.inflate(R.layout.fragment_champagne, container, false);

    champagneList = champagneView.findViewById(R.id.champagneRVList);
    champagneList.setLayoutManager(new LinearLayoutManager(getContext()));
    databaseOpenHelper = new DatabaseOpenHelper(getContext());

    //Get product list in db when db exists
    list = databaseOpenHelper.getChampagne();
    //Init adapter
    itemsAdapter = new ItemsAdapter(getContext(), list);
    //Set adapter for listview
    champagneList.setAdapter(itemsAdapter);


    return champagneView;
}


@Override
public void onPrepareOptionsMenu(@NonNull Menu menu) {
    super.onPrepareOptionsMenu(menu);

    MenuItem mSearchMenuItem = menu.findItem(R.id.action_search);
    SearchView searchView = (SearchView) mSearchMenuItem.getActionView();

    searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
        @Override
        public boolean onQueryTextSubmit(String query) {
            return false;
        }

        @Override
        public boolean onQueryTextChange(String newText) {

            Toast.makeText(getContext(), "Hello", Toast.LENGTH_SHORT).show();
            if (newText != null && TextUtils.getTrimmedLength(newText) > 0) {
                newText = newText.toLowerCase();
                List<NewModel> myList = new ArrayList<>();
                for (NewModel newModel : list) {

                    String title = newModel.getTitle().toLowerCase();
                    String description = newModel.getDescription().toLowerCase();
                    if (title.contains(newText) || description.contains(newText)) {

                        myList.add(newModel);
                        onSerach();
                    }

                }

                itemsAdapter.setFilter(myList);
            }
            else {

                list = databaseOpenHelper.getChampagne();
                itemsAdapter = new ItemsAdapter(getContext(), list);
                champagneList.setAdapter(itemsAdapter);
                itemsAdapter.notifyDataSetChanged();
            }
            return true;
        }
    });
}


@Override
public void onSerach() {
    super.onSerach();

    list = databaseOpenHelper.getSearch();
    itemsAdapter = new ItemsAdapter(getContext(), list);
    champagneList.setAdapter(itemsAdapter);
}

}

以及从BaseFragment类继承的类

public abstract class BaseFragment extends Fragment {


public DatabaseOpenHelper databaseOpenHelper;
public RecyclerView recyclerView;


@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.base_fragment, container, false);

    databaseOpenHelper = new DatabaseOpenHelper(getContext());

    //Check exists database
    File database = getContext().getDatabasePath(DatabaseOpenHelper.DBNAME);
    if(false == database.exists()) {
        databaseOpenHelper.getReadableDatabase();
        //Copy db
        if(copyDatabase(getContext())) {
            Toast.makeText(getContext(), "Copy database succes", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getContext(), "Copy data error", Toast.LENGTH_SHORT).show();
            //return;
        }

    }


    recyclerView = view.findViewById(R.id.baseFragmentRCV);
    recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));

    return view;
}


public boolean copyDatabase(Context context) {
    try {

        InputStream inputStream = context.getAssets().open(DatabaseOpenHelper.DBNAME);
        String outFileName = DatabaseOpenHelper.DBLOCATION + DatabaseOpenHelper.DBNAME;
        OutputStream outputStream = new FileOutputStream(outFileName);
        byte[]buff = new byte[1024];
        int length = 0;
        while ((length = inputStream.read(buff)) > 0) {
            outputStream.write(buff, 0, length);
        }
        outputStream.flush();
        outputStream.close();
        Log.w("MainActivity","DB copied");
        return true;
    }catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}


public void onSerach(){

    databaseOpenHelper = new DatabaseOpenHelper(getContext());

    //Check exists database
    File database = getContext().getDatabasePath(DatabaseOpenHelper.DBNAME);
    if(false == database.exists()) {
        databaseOpenHelper.getReadableDatabase();
        //Copy db
        if(copyDatabase(getContext())) {
            Toast.makeText(getContext(), "Copy database success", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(getContext(), "Copy data error", Toast.LENGTH_SHORT).show();
            return;
        }

    }

}

}

所以我删除了onStart()方法,并将这些代码行移到了onCreateView()下面。检查数据是否存在的部分在BaseFragment类中,所以现在在我的片段中,我只是从数据库中获取产品列表,因为每个片段都有自己的列表。除了search()方法,我也做了同样的事情。从SQLite数据库复制数据的方法已放在BaseFragment类中。我唯一无法完成的事情是onPrepareOptionsMenu()方法,我不知道为什么,但是在(NewModel newModel:list)list的这一行中,它返回null ...

© www.soinside.com 2019 - 2024. All rights reserved.