我在我的应用程序中对我的RecyclerView使用SearchView(内部线性布局不在操作栏中)过滤列表。在大多数设备上都可以正常工作,但是当我单击searchview时,该应用在MOTO G5S和G5S plus中崩溃。
下面是日志猫:
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.os.Handler.postAtTime(java.lang.Runnable, long)' on a null object reference
at android.widget.TextClock$2.run(TextClock.java:181)
at android.os.Handler.handleCallback(Handler.java:790)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6626)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:811)
我正在尝试开发worldclock应用程序以显示不同国家的时间。这就是我程序逻辑的方式。
我正在从MainActivity加载一个片段,该片段显示默认时区和一个添加更多时区的按钮。单击加号图标后,我将通过接口方法从MainActivity加载另一个片段,以列出各个时区。因此,所有代码逻辑都是零碎的。请参考下面的代码。预先感谢!
MainActivity.java:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FragmentManager fm = getSupportFragmentManager();
fragment = fm.findFragmentByTag("world_clock");
if(fragment!=null){
FragmentTransaction ft = fm.beginTransaction();
ft.remove(fragment);
fragment = fm.findFragmentByTag("world_clock");
}
if(fragment==null) {
FragmentTransaction ft = fm.beginTransaction();
fragment = new WorldClockFragment();
fragment.setArguments(bundle);
ft.add(R.id.fragment_container, fragment, "world_clock");
ft.addToBackStack("world_clock");
ft.commit();
}
}
@Override
public void selectTimeZones(){
FragmentManager fm = getSupportFragmentManager();
fragment = fm.findFragmentByTag("select_zones");
if(fragment!=null){
FragmentTransaction ft = fm.beginTransaction();
ft.remove(fragment);
fragment = fm.findFragmentByTag("select_zones");
}
if(fragment==null) {
FragmentTransaction ft = fm.beginTransaction();
fragment = new SelectZoneFragment();
fragment.setArguments(bundle);
ft.add(R.id.fragment_container, fragment, "select_zones");
ft.addToBackStack("select_zones");
ft.commit();
}
}
WorldClockFragment.java:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view =inflater.inflate(R.layout.activity_world_clock, container, false);
//codes to display default time zones//
Button fab =
view.findViewById(R.id.Button);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
clockInterface.selectTimeZones();
}
});
SelectZoneFragment.java:
View view;
TimeZoneAdapter timeZoneAdapter;
private String TAG="MainActivity";
private ArrayList<TimeZoneID> zoneList;
private ArrayList<TimeZoneID> displayClkList;
ArrayList<String> list;
SharedPreferences sharedpreferences;
public static final String SavedZoneIDs = "FinalPinNo";
public static final String SavedZoneStrings = "zoneStrings";
public static final String[] StringSet = new String[]{};
public static final String MyPREFERENCES = "MyPrefs" ;
private String dVal="America/New_York,Europe/London,Singapore,Asia/Kuala_Lumpur,Asia/Dubai";
ArrayList<String> savedList = new ArrayList<>();
RecyclerView recyclerView;
Context mContext;
private ArrayList<TimeZoneID> mFilteredList;
private TimeZoneAdapter.filteredList mFilteredResult;
public static SelectZoneFragment newInstance() {
SelectZoneFragment fragment = new SelectZoneFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
view = inflater.inflate(R.layout.timezone_list, container, false);
RecyclerView recyclerView = view.findViewById(R.id.support_recylerview);
LinearLayoutManager manager = new LinearLayoutManager(mContext);
recyclerView.setLayoutManager(manager);
recyclerView.setHasFixedSize(true);
sharedpreferences = getActivity().getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
String StoredZoneIDs = sharedpreferences.getString(SavedZoneIDs,dVal);
String[] storedIDArray = StoredZoneIDs.split(",");
list= new ArrayList<String> (Arrays.asList(storedIDArray));
for(String name : list){
name = name.replace(",","");
name = name.trim();
if(!name.isEmpty()){
savedList.add(name);
}
}
String[] idArray = TimeZone.getAvailableIDs();
zoneList = new ArrayList<>();
displayClkList = new ArrayList<>();
int idArrayLen=idArray.length;
for(int i=0;i<idArrayLen;i++){
TimeZoneID timeZoneID =new TimeZoneID();
timeZoneID.setTimeZoneID(idArray[i].trim());
if(list.toString().contains(idArray[i].trim()))
{
timeZoneID.setSelected(true);
displayClkList.add(timeZoneID);
}else {
timeZoneID.setSelected(false);
}
zoneList.add(timeZoneID);
}
timeZoneAdapter = new TimeZoneAdapter(zoneList,mContext);
recyclerView.setAdapter(timeZoneAdapter);
timeZoneAdapter.AdpaterOnItemClickListener(new TimeZoneAdapter.filteredList() {
@Override
public void filterlist(ArrayList<TimeZoneID> arrayList) {
}
},new TimeZoneAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
TimeZoneID tzID = zoneList.get(position);
if (tzID.isSelected()) {
tzID.setSelected(false);
displayClkList.remove(tzID);
} else {
tzID.setSelected(true);
displayClkList.add(tzID);
}
if(savedList.contains(tzID.getTimeZoneID().trim()))
{
savedList.remove(tzID.getTimeZoneID().trim());
}else{
savedList.add(tzID.getTimeZoneID().trim());
}
zoneList.set(position,tzID);
timeZoneAdapter.notifyDataSetChanged();
String savedString = savedList.toString().trim();
sharedpreferences = getActivity().getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
savedString= savedString.replace("[","").trim();
savedString=savedString.replace("]","").trim();
editor.putString(SavedZoneIDs,savedString.trim());
editor.apply();
}
});
SearchView searchView = view.findViewById(R.id.searchView);
searchView.setIconifiedByDefault(false);
searchView.setIconified(false);
searchView.clearFocus();
/* ImageView searchViewIcon = (ImageView)searchView.findViewById(android.support.v7.appcompat.R.id.search_mag_icon);
ViewGroup linearLayoutSearchView = (ViewGroup) searchViewIcon.getParent();
linearLayoutSearchView.removeView(searchViewIcon);
linearLayoutSearchView.addView(searchViewIcon);*/
searchView.setQueryHint("Search Country or City");
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String s) {
return false;
}
@Override
public boolean onQueryTextChange(final String s) {
timeZoneAdapter.getFilter().filter(s);
timeZoneAdapter.AdpaterOnItemClickListener(new TimeZoneAdapter.filteredList() {
@Override
public void filterlist(ArrayList<TimeZoneID> arrayList) {
mFilteredList=arrayList;
}
},new TimeZoneAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
TimeZoneID tzID = mFilteredList.get(position);
if (tzID.isSelected()) {
tzID.setSelected(false);
displayClkList.remove(tzID);
} else {
tzID.setSelected(true);
displayClkList.add(tzID);
}
if(savedList.contains(tzID.getTimeZoneID().trim()))
{
savedList.remove(tzID.getTimeZoneID().trim());
}else{
savedList.add(tzID.getTimeZoneID().trim());
}
mFilteredList.set(position,tzID);
timeZoneAdapter.notifyDataSetChanged();
String savedString = savedList.toString().trim();
sharedpreferences = getActivity().getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedpreferences.edit();
savedString= savedString.replace("[","").trim();
savedString=savedString.replace("]","").trim();
editor.putString(SavedZoneIDs,savedString.trim());
editor.apply();
}
});
return true;
}
});
return view;
}
timezone_list.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:clickable="true"
android:focusable="true"
android:orientation="vertical">
<SearchView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/searchView"
android:background="@drawable/background"
android:layout_margin="5dp"
/>
<android.support.v7.widget.RecyclerView
android:id="@+id/support_recylerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:clipToPadding="false"
android:paddingTop="4dp"
android:paddingBottom="4dp"/>
</LinearLayout>
TimeZoneAdapter.java
public void AdpaterOnItemClickListener(filteredList filteredList,final TimeZoneAdapter.OnItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
this.mFilteredResult = filteredList;
}
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
public interface filteredList{
void filterlist(ArrayList<TimeZoneID> arrayList);
}
public TimeZoneAdapter(ArrayList<TimeZoneID> zoneList, Context c) {
this.zoneList=zoneList;
mFilteredList=zoneList;
mContext=c;
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView zoneID;
public TextView gmt;
CheckBox chk;
public ViewHolder(View view) {
super(view);
gmt = view.findViewById(R.id.GMT);
zoneID = (TextView) view.findViewById(R.id.timeZoneID);
chk = (CheckBox) view.findViewById(R.id.chk);
chk.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mItemClickListener.onItemClick(v, getAdapterPosition());
}
});
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.zone_item_list, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
ViewHolder zoneListHolder = (ViewHolder) holder;
TimeZoneID timeZoneID = mFilteredList.get(position);
zoneListHolder.zoneID.setText(timeZoneID.getTimeZoneID());
zoneListHolder.chk.setChecked(timeZoneID.isSelected());
TimeZone timeZone = TimeZone.getTimeZone(timeZoneID.getTimeZoneID());
int off = timeZone.getRawOffset() / (60 * 1000);
int hrs = off / 60;
int mins = off % 60;
String hr = Integer.toString(hrs);
if(String.valueOf(hr.charAt(0)).equalsIgnoreCase("-")){
zoneListHolder.gmt.setText("GMT " + hrs + "." + mins);
}else{
zoneListHolder.gmt.setText("GMT " +"+"+ hrs + "." + mins);
}
}
@Override
public int getItemCount() {
return mFilteredList.size();
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
mFilteredList = zoneList;
} else {
ArrayList<TimeZoneID> filteredList = new ArrayList<>();
for (TimeZoneID androidVersion : zoneList) {
if (androidVersion.getTimeZoneID().toLowerCase().contains(charString) ) {
filteredList.add(androidVersion);
}
}
mFilteredList = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = mFilteredList;
filterResults.count = mFilteredList.size();
return filterResults;
}
@SuppressWarnings("unchecked")
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
mFilteredList = (ArrayList<TimeZoneID>) filterResults.values;
mFilteredResult.filterlist(mFilteredList);
notifyDataSetChanged();
}
};
}