I'm trying to understand AsyncTask in Android. I can't understand how do we pass parameters. In this code :
protected class AsyncLogin extends AsyncTask<String, JSONObject, Boolean> {
String userName = null;
#Override
protected Boolean doInBackground(String... params)
{
RestAPI api = new RestAPI();
boolean userAuth = false;
try
{
JSONObject jsonObj = api.UserAuthentication(params[0], params[1]);
JSONParser parser = new JSONParser();
userAuth = parser.parseUserAuth(jsonObj);
userName = params[0];
}
catch (Exception e)
{
Log.d("AsyncLogin", e.getMessage());
}
return userAuth;
}
#Override
protected void onPreExecute()
{
super.onPreExecute();
Toast.makeText(context, "Please wait...", Toast.LENGTH_SHORT).show();
}
#Override
protected void onPostExecute(Boolean result)
{
if(result) {
Intent i = new Intent(LoginActivity.this, UserDetailsActivity.class);
i.putExtra("username", userName);
startActivity(i);
}
else
{
Toast.makeText(context, "Not valid username/password", Toast.LENGTH_SHORT).show();
}
}
}
I can't understand why do we use <String, JSONObject, Boolean> in
protected class AsyncLogin extends AsyncTask<String, JSONObject, Boolean>
What do String, JSONObject and Boolean refer to? Can you explain it to me? Thanks.
AsyncTask (Type1, Type2, Type3) uses argument types:
Type1 is the type of argument you pass when you call execute (received in doInBackground)
Type2 is the type of the argument you pass to onProgressUpdate when you call publishProgress.
Type3 is the type of argument you pass to onPostExecute, which is what you return from doInBackground.
Asynch Task implementation allows you one type parameter as argument. But you can pass it more type parameters, by declaring one parameterized constructor to it.
e.g.
class YourAsynchTask extends AsyncTask<ArgumentObject, ProgressObject, ResultObject> {
......
ObjectType1 argument1;
ObjectType2 argument2;
ObjectType3 argument3;
YourAsynchTask(ObjectType1 arg1, ObjectType2 arg2, ObjectType3 arg3) {
argument1 = arg1;
argument2 = arg2;
argument3 = arg3;
}
// rest of the method of your asynch task like doInBackground, etc.
}
You can call this type of asynch task like this :
new YourAsynchTask(arg1, arg2, arg3).execute(argumentObjet);
public class Child
{
String child_title;
public String getChild_title() {
return child_title;
}
public void setChild_title(String child_title) {
this.child_title = child_title;
}
}
public class Parent
{
String header_title;
ArrayList<Child>childArrayList;
public ArrayList<Child> getChildArrayList() {
return childArrayList;
}
public void setChildArrayList(ArrayList<Child> childArrayList) {
this.childArrayList = childArrayList;
}
public String getHeader_title() {
return header_title;
}
public void setHeader_title(String header_title) {
this.header_title = header_title;
}
}
public class ExpandAdapter extends BaseExpandableListAdapter
{
Context context;
ArrayList<Parent>parentArrayList;
LayoutInflater li;
public ExpandAdapter(Context context, ArrayList<Parent> parentArrayList)
{
this.context=context;
this.parentArrayList=parentArrayList;
li= (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getGroupCount() {
return parentArrayList.size();
}
#Override
public int getChildrenCount(int groupPosition) {
return parentArrayList.get(groupPosition).getChildArrayList().size();
}
#Override
public Object getGroup(int groupPosition) {
return parentArrayList.get(groupPosition);
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return parentArrayList.get(groupPosition).getChildArrayList().get(childPosition);
}
#Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
#Override
public boolean hasStableIds() {
return true;
}
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
convertView=li.inflate(R.layout.customheader,null);
TextView tv= (TextView) convertView.findViewById(R.id.tv);
tv.setText(parentArrayList.get(groupPosition).getHeader_title());
return convertView;
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
convertView=li.inflate(R.layout.customchild,null);
TextView tv1= (TextView) convertView.findViewById(R.id.tv1);
tv1.setText(parentArrayList.get(groupPosition).childArrayList.get(childPosition).getChild_title());
return convertView;
}
#Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
}
ExpandableListView expandlv;
ArrayList<Parent>parentArrayList;
ArrayList<Child>childArrayList;
Parent parent;
Child child;
String header_title[]={"No","Alpha","Funcation"};
String child_notitle[]={"1","2","3"};
String child_alphatitle[]={"A","B","C"};
String child_functiontitle[]={"F1","F2","F3"};
Context context=this;
ExpandAdapter expandadapter;
expandlv= (ExpandableListView) findViewById(R.id.expandlv);
parentArrayList =new ArrayList<>();
for(int i=0;i<header_title.length;i++)
{
parent =new Parent();
parent.setHeader_title(header_title[i]);
childArrayList =new ArrayList<>();
if(i==0)
{
for(int j=0;j<child_notitle.length;j++)
{
child =new Child();
child.setChild_title(child_notitle[j]);
childArrayList.add(child);
parent.setChildArrayList(childArrayList);
}
}
if(i==1)
{
for(int j=0;j<child_alphatitle.length;j++)
{
child=new Child();
child.setChild_title(child_alphatitle[j]);
childArrayList.add(child);
parent.setChildArrayList(childArrayList);
}
}
if(i==2)
{
for(int j=0;j<child_functiontitle.length;j++)
{
child=new Child();
child.setChild_title(child_functiontitle[j]);
childArrayList.add(child);
parent.setChildArrayList(childArrayList);
}
}
parentArrayList.add(parent);
}
expandadapter=new ExpandAdapter(context,parentArrayList);
expandlv.setAdapter((ExpandableListAdapter) expandadapter);
customheader
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Header Title"
android:textColor="#android:color/darker_gray"
android:textSize="30dp"
android:layout_centerHorizontal="true"
android:id
enter code here
customchild
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tv1"
android:layout_centerHorizontal="true"
android:text="Child Title"
android:textColor="#android:color/holo_green_dark"
android:textSize="20dp"/>
</RelativeLayout>
<ExpandableListView
android:layout_width="wrap_content"
android:layout_margin="20dp"
android:layout_height="wrap_content"
android:id="#+id/expandlv"/>
View Pager With Slide
<android.support.design.widget.TabLayout
android:id="#+id/tabLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary">
</android.support.design.widget.TabLayout>
<android.support.v4.view.ViewPager
android:id="#+id/viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:padding="#dimen/_10sdp" />
TabLayout tabLayout;
ViewPager viewPager;
tabLayout=(TabLayout)findViewById(R.id.tabLayout);
viewPager=(ViewPager)findViewById(R.id.viewPager);
tabLayout.addTab(tabLayout.newTab().setText(""));
tabLayout.addTab(tabLayout.newTab().setText(""));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
final MyAdapter adapter = new MyAdapter(MainActivity.this,getSupportFragmentManager(), tabLayout.getTabCount());
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
public class MyAdapter extends FragmentPagerAdapter {
private Context myContext;
int totalTabs;
public MyAdapter(Context context, FragmentManager fm, int totalTabs) {
super(fm);
myContext = context;
this.totalTabs = totalTabs;
}
// this is for fragment tabs
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
Fragment0 zero = new Fragment0();
return zero;
case 1:
Fragment1 one = new Fragment1();
return one;
default:
return null;
}
}
// this counts total number of tabs
#Override
public int getCount() {
return totalTabs;
}
}
Related
I was testing my app on many device and it was working fine...Untill I tested on an android device running android 7.1 the recycler view is gone while it exists on other devices tahte my Code:
RecyclerGridLayoutAdapter:
public class RecyclerGridLayoutAdapter extends RecyclerView.Adapter<RecyclerGridLayoutAdapter.ViewHolder>{
private int resource;
private ArrayList<Item> contacts;
private TreeMap<String,ArrayList<Contact>> gridsMap;
private String searchedString;
private Context activity;
private String myNumber;
public RecyclerGridLayoutAdapter(int resource, ArrayList<Item> contacts,Context activity) {
this.resource = resource;
this.contacts = contacts;
this.activity=activity;
gridsMap= DatabaseHandler.getDataBaseHandler(activity).getContactsByAlphabets();
loadData();
searchedString="";
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
v= LayoutInflater.from(activity).inflate(resource,parent,false);
ViewHolder vh=new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
Log.wtf("begin ","inserting "+contacts.get(position).type);
if(contacts.get(position).type==0){
holder.header.setVisibility(View.VISIBLE);
holder.header.setText(contacts.get(position).alphabet);
holder.name.setVisibility(View.GONE);
holder.image.setVisibility(View.GONE);
}
else {
holder.header.setVisibility(View.GONE);
holder.name.setVisibility(View.VISIBLE);
holder.image.setVisibility(View.VISIBLE);
SharedPreferences prefs=activity.getSharedPreferences("myNumber",0);
final String myNumber=prefs.getString("number","not pund");
holder.name.setText(contacts.get(position).contact.name);
if(contacts.get(position).contact.isRegistered.equalsIgnoreCase("true")){
holder.image.setBackgroundResource(R.drawable.contact_offline_pic);
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent=new Intent(activity, ChatRoomActivity.class);
AppMasterManager.activity=ChatRoomActivity.class;
intent.putExtra("room",contacts.get(position).contact.room);
intent.putExtra("contact_name",contacts.get(position).contact.name);
intent.putExtra("myNumber",myNumber);
if (contacts.get(position).contact.isPrivate.equalsIgnoreCase("true")){
if (!DatabaseHandler.getDataBaseHandler(activity).numberExist(contacts.get(position).contact.phone_number)){
DatabaseHandler.getDataBaseHandler(activity).addPrivateContact(contacts.get(position).contact);
try {
ChatService.bind.getService().joinANumber(contacts.get(position).contact);
} catch (JSONException e) {
e.printStackTrace();
}
}
intent.putExtra("account", Accounts.SECONDARY_ACCOUNT);
}else {
intent.putExtra("account", Accounts.PRIMARY_ACCOUNT);
}
Log.wtf("from grid adapter inflater",contacts.get(position).contact.room);
activity.startActivity(intent);
}
});
if(contacts.get(position).contact.state.equalsIgnoreCase("offline")){
holder.image.setBackgroundResource(R.drawable.contact_offline_pic);
}
else {
holder.image.setBackgroundResource(R.drawable.contact_online_pic);
}
}
else {
holder.image.setBackgroundResource(R.drawable.contact_unregistered_pic);
}
}
}
#Override
public int getItemCount() {
return contacts.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView header;
public TextView name;
public ImageView image;
public ViewHolder(View itemView) {
super(itemView);
header=(TextView)itemView.findViewById(R.id.first_char_header);
name=(TextView)itemView.findViewById(R.id.contact_name);
image=(ImageView)itemView.findViewById(R.id.image_grid_contact);
}
}
#Override
public int getItemViewType(int position) {
if(contacts.get(position).type==0){
return 4;
}
else {
return 1;
}
}
public void search(String pattern){
searchedString=pattern;
if(!TextUtils.isEmpty(pattern)) {
searchedString=pattern;
gridsMap.clear();
gridsMap=DatabaseHandler.getDataBaseHandler(activity).getContactsByAlphabetsWithPattern(pattern);
contacts.clear();
loadData();
}
else {
gridsMap.clear();
gridsMap=DatabaseHandler.getDataBaseHandler(activity).getContactsByAlphabets();
contacts.clear();
loadData();
}
notifyDataSetChanged();
}
public void updateDataSet(){
if(!TextUtils.isEmpty(searchedString)){
contacts.clear();
gridsMap.clear();
gridsMap=DatabaseHandler.getDataBaseHandler(activity).getContactsByAlphabetsWithPattern(searchedString);
loadData();
notifyDataSetChanged();
}
else {
contacts.clear();
gridsMap.clear();
gridsMap=DatabaseHandler.getDataBaseHandler(activity).getContactsByAlphabets();
loadData();
notifyDataSetChanged();
}
}
void loadData(){
for(String c:gridsMap.keySet()){
contacts.add(new Item(0,c));
Log.wtf("add","+");
for(Contact d:gridsMap.get(c)){
contacts.add(new Item(1,c,d));
}}
}
public void searchOnline(final String pattern) throws JSONException {
if(!TextUtils.isEmpty(pattern)){
JSONObject object=new JSONObject();
object.put("pattern",pattern);
JsonObjectRequest request_json = new JsonObjectRequest(WebServiceApi.SEARCH_SECONDARY_CONTACTS_ONLINE,object, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
if(response.getJSONArray("res").length()>0){
contacts.clear();
Log.w("result ",response.getJSONArray("res").getJSONObject(0).getJSONObject("secondary_account").getString("user_name").toString());
contacts.add(new Item(0,pattern.toCharArray()[0]+""));
for(int i=0;i<response.getJSONArray("res").length();i++){
String name=response.getJSONArray("res").getJSONObject(i).getJSONObject("secondary_account").getString("user_name");
String phone_number=response.getJSONArray("res").getJSONObject(i).getString("phone_number");
String room;
if(phone_number.compareTo(myNumber)>0){
room=phone_number+myNumber;
}
else {
room=myNumber+phone_number;
}
Contact contact=new Contact();
contact.name=name;
contact.room=room;
contact.phone_number=phone_number;
contact.isRegistered="true";
contact.state="offline";
contact.isPrivate="true";
contacts.add(new Item(1,pattern.toCharArray()[0]+"",contact));
}
notifyDataSetChanged();
}
else{
contacts.clear();
loadData();
notifyDataSetChanged();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener(){
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("No Activity", error.getMessage());
}
});
AppController.getInstance().addToRequestQueue(request_json);
}
else {
contacts.clear();
loadData();
notifyDataSetChanged();
}
}
public void setNumber(String number){
myNumber=number;
}
}
ContactsFragement:
public class ContactsFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
private OnContactsFragementInteraction mListener;
private RecyclerView listContacts;
private GridLayoutManager manager;
private HashMap<String,Contact> roomMaps;
private String number;
private boolean isLoaded=false;
private RecyclerGridLayoutAdapter adapter;
public ContactsFragment() {
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment ContactsFragment.
*/
// TODO: Rename and change types and number of parameters
public static ContactsFragment newInstance(String param1, String param2) {
ContactsFragment fragment = new ContactsFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_contacts, container, false);
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mListener.pressed();
if(savedInstanceState==null){Toast.makeText(getActivity(),"First Time running this fragment",Toast.LENGTH_SHORT).show();}
roomMaps = new HashMap<>();
listContacts = (RecyclerView) getActivity().findViewById(R.id.list_contacts);
EditText contact_search_box = (EditText) getActivity().findViewById(R.id.search_box_contacts);
contact_search_box.clearFocus();
number = this.getArguments().getString("number");
// contactsListAdapter = new ContactsListAdapterAlternative(getActivity(), new ArrayList<GridLayoutAdapter>(), R.layout.list_contacts_item);
// listContacts.setAdapter(contactsListAdapter);
manager=new GridLayoutManager(getActivity(),4);
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
return (adapter.getItemViewType(position));
}
});
adapter=new RecyclerGridLayoutAdapter(R.layout.list_contacts_item,new ArrayList<Item>(),getActivity());
adapter.setNumber(number);
manager.setOrientation(LinearLayoutManager.VERTICAL);
listContacts.setLayoutManager(manager);
listContacts.setHasFixedSize(true);
listContacts.setAdapter(adapter);
EditText search_online_box=getActivity().findViewById(R.id.search_online);
search_online_box.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
try {
adapter.searchOnline(s.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
contact_search_box.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
adapter.search(charSequence.toString());
}
#Override
public void afterTextChanged(Editable editable) {
}
});
isLoaded=true;
}
// TODO: Rename method, update argument and hook method into UI event
public void onButtonPressed(Uri uri) {
if (mListener != null) {
}
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnContactsFragementInteraction) {
mListener = (OnContactsFragementInteraction) context;
mListener.pressed();
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
public void updateState(String room,HashMap<String,String> map) {
if(adapter!=null)
adapter.updateDataSet();
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnContactsFragementInteraction {
// TODO: Update argument type and name
void pressed();
ChatService getService();
void setRoutablity(boolean routablity);
}
}
fragment_contacts:
<RelativeLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/contactsFragment"
xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal"
android:id="#+id/topSearchBar"
android:weightSum="2">
<EditText
android:id="#+id/search_box_contacts"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:padding="10dp"
android:textSize="15sp"
android:hint="search contacts"
android:background="#beddeb"/>
<EditText
android:id="#+id/search_online"
android:layout_width="0dp"
android:layout_height="match_parent"
android:hint="search online"
android:padding="10dp"
android:textSize="15sp"
android:background="#5fc0e9"
android:layout_weight="1"/>
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/list_contacts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/topSearchBar"
android:scrollbars="vertical"
tools:listitem="#layout/list_contacts_item">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
list_contact_item:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/first_char_header"
android:layout_width="match_parent"
android:layout_height="40dp"
android:text="a"
android:paddingTop="6dp"
android:paddingLeft="8dp"
android:textSize="25sp"
android:textColor="#c1292f"
android:background="#f2f2f2"
/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">
<TextView
android:lines="2"
android:id="#+id/contact_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Abdallah"
android:padding="5dp"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:src="#drawable/contact_small"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:id="#+id/image_grid_contact"
android:background="#drawable/contact_offline_pic"/>
</LinearLayout>
</LinearLayout>
This gridView is simply a contacts grid where it shows all the contacts available and registered in my network...
On log it shows that it recognizes that there are registered contacts and even it receives a message and if I open the chats tab i see that this listview contact send a message though no contact is appearing in the recycler view...
I am trying to display an Empty view in an app that displays movie posters. I am using a recyclerview - for example when I put my device in flight mode and click refresh I was expecting the app to display the empty state view but this is not the case.
The posters are still displayed in the Activity. Why is this the case?
The data is from the moviedatabase api & I am retrieving a movie title & relative image path
MAIN ACTIVITY
public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Movie>> {
private static final String LOG_TAG = MainActivity.class.getSimpleName();
private static final int LOADER_ID = 1;
private MovieAdapter mMovieAdapter;
private RecyclerView mRecyclerView;
private GridLayoutManager mGridLayoutManager;
private LoaderManager mLoaderManager;
private View mLoadingIndicator;
private TextView mEmptyTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLoadingIndicator = findViewById(R.id.loadingIndicator);
mEmptyTextView = (TextView) findViewById(R.id.emptyStateTextView);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mLoadingIndicator.setVisibility(View.VISIBLE);
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mGridLayoutManager = new GridLayoutManager(this, 2);
mRecyclerView.setLayoutManager(mGridLayoutManager);
mMovieAdapter = new MovieAdapter();
mRecyclerView.setAdapter(mMovieAdapter);
mLoaderManager = getSupportLoaderManager();
mLoaderManager.initLoader(LOADER_ID, null, this);
}
public void showMovieDataView() {
mEmptyTextView.setVisibility(View.INVISIBLE);
mRecyclerView.setVisibility(View.VISIBLE);
}
public void showErrorMessage() {
mRecyclerView.setVisibility(View.INVISIBLE);
mEmptyTextView.setVisibility(View.VISIBLE);
}
#Override
public Loader<List<Movie>> onCreateLoader(int id, Bundle args) {
return new MovieLoader(this, TmdbUrlUtils.BASE_URL);
}
#Override
public void onLoadFinished(Loader<List<Movie>> loader, List<Movie> data) {
mLoadingIndicator.setVisibility(View.INVISIBLE);
if (data == null) {
showErrorMessage();
} else {
showMovieDataView();
mMovieAdapter.setMovieData(data);
}
}
#Override
public void onLoaderReset(Loader<List<Movie>> loader) {
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main_menu, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
switch (id) {
case R.id.refresh:
mLoadingIndicator.setVisibility(View.VISIBLE);
mMovieAdapter.setMovieData(null);
getSupportLoaderManager().restartLoader(LOADER_ID, null, this);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
}
ADAPTER CLASS
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.ViewHolder> {
List<Movie> mMovieList;
public static final String BASE_POSTER_URL = "http://image.tmdb.org/t/p/w185";
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Context context = holder.mImageView.getContext();
String imagePath = mMovieList.get(position).getmPosterPath();
Uri baseUri = Uri.parse(BASE_POSTER_URL);
Uri.Builder builder = baseUri.buildUpon();
builder.appendEncodedPath(imagePath);
String imageUrl = builder.toString();
Picasso.with(context).load(imageUrl).into(holder.mImageView);
}
#Override
public int getItemCount() {
if (null == mMovieList) return 0;
return mMovieList.size();
}
public void setMovieData(List<Movie> data) {
mMovieList = data;
this.notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ImageView mImageView;
public ViewHolder(View itemView) {
super(itemView);
mImageView = (ImageView) itemView.findViewById(R.id.imagePoster);
}
}
}
ACTIVITY_MAIN XML
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f48fb1"
tools:context="com.example.android.cinemate.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#d4e157">
</android.support.v7.widget.RecyclerView>
<ProgressBar
android:id="#+id/loadingIndicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="invisible"/>
<TextView
android:id="#+id/emptyStateTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#f44336"
android:text="No network detected!"
android:visibility="invisible"/>
</FrameLayout>
CUSTOM OBJECT
public class Movie implements Parcelable {
public static final Creator<Movie> CREATOR = new Creator<Movie>() {
#Override
public Movie createFromParcel(Parcel in) {
return new Movie(in);
}
#Override
public Movie[] newArray(int size) {
return new Movie[size];
}
};
private String mTitle;
private String mPosterPath;
public Movie(String title, String posterPath) {
this.mTitle = title;
this.mPosterPath = posterPath;
}
protected Movie(Parcel in) {
mTitle = in.readString();
mPosterPath = in.readString();
}
public String getmTitle() {
return mTitle;
}
public void setmTitle(String mTitle) {
this.mTitle = mTitle;
}
public String getmPosterPath() {
return mPosterPath;
}
public void setmPosterPath(String mPosterPath) {
this.mPosterPath = mPosterPath;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeString(mTitle);
parcel.writeString(mPosterPath);
}
}
This is a LOG of what gets called when flight mode is on:
Refresh selected with Flight Mode on
TEST......MainActivity onCreateLoader() called
TEST.......MovieLoader loadInBackground() called
TEST.......NetworkUtils getDataFromNetwork() called
TEST.......NetworkUtils createUrl() called
TEST.......NetworkUtils makeHttpRequest() called
TEST.......MovieJsonUtils parseJson() called
TEST......MainActivity onLoadFinished() called
TEST......MainActivity showMovieData() called
I'm migrating from ListView to an RecyclerView and last thing I'm stuck with is updating one of fields. My App has a simple list with some images found on internet. When you choose one, image gets downloaded to a phone for later offline viewing. Adapter gets data from SQLite databaseso when you tap on some image database gets updated (text changes from a "Tap here to Download" to a "Downloaded") and RecyclerView should follow.
I had same problem with ListView but there I just called populateList(); each time App updated db. I know it's not the ideal solution but it worked. Now I want to do it right with notifyDataSetChanged() or even better notifyItemChanged(position) but I can't get it working.
Anyway here's the code, sorry for being a little bit messy. This is just a test code (RecyclerView code is from samples):
public class RecyclerFragment extends Fragment {
private imgAdapter mAdapter;
private DatabaseHandler db;
private ProgressDialog mProgressDialog;
public RecyclerFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
db = new DatabaseHandler(getActivity());
List<Images> listdb = db.getImages();
mAdapter = new ImgAdapter(getActivity(), listdb);
db.close();
View view = inflater.inflate(R.layout.fragment_main, container, false);
RecyclerView recyclerView = (RecyclerView) view.findViewById(android.R.id.list);
recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new GridLayoutManager(
getActivity(), getResources().getInteger(R.integer.list_columns)));
recyclerView.setAdapter(mAdapter);
return view;
}
private class ImgAdapter extends RecyclerView.Adapter<ViewHolder>
implements ItemClickListener {
public List<Images> mList;
private Context mContext;
public ImgAdapter(Context context, List<Images> listdb) {
super();
mContext = context;
mList = listdb;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.list_row1, parent, false);
return new ViewHolder(view, this);
}
#Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
Images image = mList.get(position);
holder.mTitle.setText(image.getTitle());
holder.mDownloadStatus.setText(image.getDownloadStatus());
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemCount() {
return mList == null ? 0 : mList.size();
}
#Override
public void onItemClick(View view, int position) {
switch (position) {
case 0:
Log.v("POSITION 0:", " " + position);
break;
case 1:
/*
some logic nvm
*/
String imgurl = "http:/...";
String imagename = "Second image";
new GetImages(imgurl, imagename).execute();
/*
I've tried mAdapter.notitfy... , no luck aswell
This does nothing:
*/
notifyItemChanged(position);
notifyDataSetChanged();
break;
//....
}
}
}
private static class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
TextView mTitle;
TextView mDownloadStatus;
ItemClickListener mItemClickListener;
public ViewHolder(View view, ItemClickListener itemClickListener) {
super(view);
mTitle = (TextView) view.findViewById(R.id.text1);
mDownloadStatus = (TextView) view.findViewById(R.id.text2);
mItemClickListener = itemClickListener;
view.setOnClickListener(this);
}
#Override
public void onClick(View v) {
mItemClickListener.onItemClick(v, getPosition());
}
}
interface ItemClickListener {
void onItemClick(View view, int position);
}
/*
This is my AsyncTask class used for downloading image and updating db
I removed some code just to to make it cleaner
*/
private class GetImages extends AsyncTask<Object, Object, Object> {
private final String requestUrl;
private final String imagename_;
private String imagename;
public int numberofbits;
private GetImages(String requestUrl, String _imagename_) {
this.requestUrl = requestUrl;
this.imagename_ = _imagename_;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
//pDialog...
}
#Override
protected Object doInBackground(Object... objects) {
try {
URL url = new URL(requestUrl);
URLConnection conn = url.openConnection();
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
numberofbits = bitmap.getByteCount();
} catch (Exception ignored) {
}
return null;
}
#Override
protected void onPostExecute(Object o) {
if (!ImageStorage.checkifImageExists(imagename)) {
ImageStorage.saveToSdCard(bitmap, imagename_);
}
if (numberofbits > 50) {
db = new DatabaseHandler(getActivity());
db.updateImages(new Images(dbid, "Downloaded", imagename_));
db.close();
//populateList(); -> THIS I USED FOR A LISTVIEW
Toast.makeText(getActivity(), "Downloaded!", Toast.LENGTH_SHORT).show();
mProgressDialog.dismiss();
//If image gets downloaded open it in Viewer class
Intent intent = new Intent(getActivity(), DisplayImage.class);
intent.putExtra("imagePath", path);
startActivity(intent);
} else {
//Toast.makeText(getActivity(), "Unable to download", Toast.LENGTH_SHORT).show();
mProgressDialog.dismiss();
}
}
}
}
Here's Images class
public class Images {
//private variables
private int _id;
private String _title;
private String _downloadstatus;
// Empty constructor
public Images () {
}
// constructor
public Images(int id, String title, String downloadstatus) {
this._id = id;
this._title = title;
this._downloadstatus = downloadstatus;
}
public int getID() {
return this._id;
}
public void setID(int id) {
this._id = id;
}
public String getTitle() {
return this._title;
}
public void setTitle(String title) {
this._title = title;
}
public String getDownloadStatus() {
return this._downloadstatus;
}
public void setDownloadStatus(String downloadstatus) {
this._downloadstatus = downloadstatus;
}
}
And here's an XML (I'm trying to update "text2"):
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:foreground="?attr/selectableItemBackground"
android:layout_height="wrap_content"
android:padding="8dp">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="match_parent"
>
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="#dimen/imagename"
android:textStyle="bold"
android:paddingStart="4sp"
android:paddingEnd="40sp" />
<TextView
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/text1"
android:textSize="#dimen/downloaded"
android:paddingStart="4sp"
android:paddingEnd="1sp"
android:textColor="#color/graydownloaded" />
</RelativeLayout>
</FrameLayout>
Okay I finally got it working and It was actually quite simple...
//....
if (numberofbits > 50) {
db = new DatabaseHandler(getActivity());
db.updateImages(new Images(dbid, "Downloaded", imagename_));
//This is what I added:
List<Images> listdb = db.getImages();
mAdapter = new ImgAdapter(getActivity(), listdb);
recyclerView.setAdapter(mAdapter);
db.close();
//populateList(); -> THIS I USED FOR A LISTVIEW
Toast.makeText(getActivity(), "Downloaded!", Toast.LENGTH_SHORT).show();
mProgressDialog.dismiss();
//If image gets downloaded open it in Viewer class
Intent intent = new Intent(getActivity(), DisplayImage.class);
intent.putExtra("imagePath", path);
startActivity(intent);
} else {
//...
Try doing this: Override in your adapter the getItemId method like this
#Override
public long getItemId(int position) {
return mList.get(position).getID();
}
And add this line after recyclerView.setHasFixedSize(true) :
recyclerView.setHasStableId(true);
EDIT:
mAdapter.setHasStableId(true);
Let me know if that did the trick.
I am using the material design tabs. I have different fragment on each tab. In one fragment I have edit Text and button and bellow is list view. ListView is populate from api and also message is create using the api(POST).
After user click on the createMessageBtn it create the message to server. But not update the listview after on click event is occur. Until Fragment Message tab not reload the newly created message not showing. When I move to different tabs and then again came to message tab then newly created message is in the listView. I want to update the listview after the createMessageBtn clicked or reload the fragment.
Here is fragment_message.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/top" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Create Message"
android:id="#+id/createMessagelbl"
android:textAlignment="center"
android:textStyle="bold"
android:textSize="14sp"
android:layout_marginTop="6dp"
android:gravity="center_horizontal"
/>
<EditText
android:layout_width="match_parent"
android:layout_height="80dp"
android:id="#+id/createMessagetxt"
android:layout_below="#+id/createMessagelbl"
android:layout_marginTop="10dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="5dp"
android:textColor="#ff7e7e7e"
android:inputType="text" />
<Button
android:layout_width="80dp"
android:layout_height="30dp"
android:text="Post"
android:id="#+id/createMessagebtn"
android:layout_below="#+id/createMessagetxt"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:background="#drawable/button"
android:layout_marginBottom="10dp"
android:layout_marginTop="1dp"
android:textColor="#ff4a8aff" />
</RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_below="#+id/top" android:padding="8dp"
android:layout_marginTop="6dp">
<ListView
android:id="#+id/messagesListView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:dividerHeight="1dp"
/>
</RelativeLayout>/
</RelativeLayout>
Here Message Fragment.java
public class Message extends Fragment implements View.OnClickListener {
private ArrayList<Messages> mMessagesList = new ArrayList<>();
private MessagesListAdapter mAdapter;
ListView mListView;
EditText mMessageText;
Button mMessagePostBtn;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getMessages();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_messages, container, false);
mListView = (ListView) view.findViewById(R.id.messagesListView);
mMessageText = (EditText) view.findViewById(R.id.createMessagetxt);
mMessagePostBtn = (Button) view.findViewById(R.id.createMessagebtn);
mMessagePostBtn.setOnClickListener(this);
mAdapter = new MessagesListAdapter(getActivity().getApplicationContext(), mMessagesList);
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
});
return view;
}
private void getMessages() {
String URL ="Url";
JsonObjectRequest req = new JsonObjectRequest(URL, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
// Here I am adding the result to mMessagesList
} catch (JSONException e) {
e.printStackTrace();
}
mAdapter.setData(mMessageList);
mAdapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.e("Error: ", error.getMessage());
}
}) {
// Here is my token
String token = "Token " + getToken;
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Authorization", token);
return headers;
}
};
AppController.getInstance().addToRequestQueue(req);
}
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.createMessagebtn:
if (mMessageText.getText().toString().length() == 0) {
mMessageText.setError("Please Enter the Message");
} else {
String url = "Url";
postMessage(url, mMessageText.getText().toString());
mMessageText.setText("");
getMessages();
/*FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
MessagesFragment messageFragment = new MessagesFragment();
ft.detach(messageFragment);
ft.attach(messageFragment);
ft.commit();*/
}
}
}
public void postMessage(String url, final String message) {
ToastMessage.showToastMessage(getActivity().getApplicationContext(), message);
StringRequest postRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
// Here Message is post Successfully
getMessages();
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// error
Log.d("Error.Response", error.getMessage());
}
}
) {
// Here is my token
String token = "Token " + getToken;
#Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<String, String>();
params.put("message", message);
return params;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> header = new HashMap<String, String>();
header.put("Authorization", token);
return header;
}
};
AppController.getInstance().addToRequestQueue(postRequest);
}
}
Here is my PageAdapter.java
public class PagerAdapter extends FragmentStatePagerAdapter {
final int PAGE_COUNT = 5;
private String tabTitles[] = new String[] { "Some", "Some", "Some","Messages", "Some" };
private Context context;
public PagerAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
SomeFragment some = new SomeFragment ();
return some ;
case 1:
SomeFragment some = new SomeFragment ();
return market;
case 2:
SomeFragment some = new SomeFragment ();
return some ;
case 3:
MessagesFragment messages = new MessagesFragment();
return messages;
case 4:
SomeFragment some = new SomeFragment ();
return some ;
default:
return null;
}
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
Here MessageListAdapter.java
public class MessagesListAdapter extends BaseAdapter {
private Context mContext;
private ArrayList<Messages> messagesItems;
private LayoutInflater mInflater;
public MessagesListAdapter(Context mContext, ArrayList<Messages> messagesItems) {
this.mContext = mContext;
this.messagesItems = messagesItems;
}
public void setData(ArrayList<Messages> messagesItems) {
this.messagesItems = messagesItems;
notifyDataSetChanged();
}
public int getCount() {
return messagesItems.size();
}
#Override
public Object getItem(int position) {
return messagesItems.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (mInflater == null)
mInflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = mInflater.inflate(R.layout.messages_list_row, null);
//here my view from xml files
Messages m = messagesItems.get(position);
//here My populate xml file with data
return convertView;
}
}
Im trying to implement a contact listview with a pageloader to manage loading on demand and a searchview to search within the list, but I cant get it working. I am all contacts in app.allContacts. The problem is that the searchview is not working. and I dont know if its the loaderCallback or the searchview.
public class ContactsFragment extends SherlockListFragment {
private SeparatedListAdapter sl;
private SumaApplication app;
private ContactAdapter allContacts;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
app = (SumaApplication) getActivity().getApplication();
allContacts = new ContactAdapter(getActivity());
sl = new SeparatedListAdapter(new HeaderAdaptor(getActivity(), R.layout.section_title, new ArrayList<String>()));
sl.addSection(getResources().getString(R.string.all_contacts), allContacts);
setListAdapter(sl);
getLoaderManager().initLoader(0, null, loaderCallbak);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_list_contacts, container, false);
((SearchView) v.findViewById(R.id.contacts_to)).setOnQueryTextListener(queryListener);
searchView = new SearchViewImpl(getActivity());
searchView.setOnQueryTextListener(queryListener);
searchView.setOnCloseListener(closeListener);
searchView.setIconifiedByDefault(true);
return v;
}
#Override
public void onDestroyView() {
super.onDestroyView();
}
private SearchView searchView;
private OnCloseListener closeListener = new OnCloseListener() {
#Override
public boolean onClose() {
searchView.setQuery(null, true);
return true;
}
};
#Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
Intent callIntent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:" +((Contact) l.getItemAtPosition(position)).getInfo()));
startActivity(callIntent);
}
private LoaderCallbacks<List<Contact>> loaderCallbak = new LoaderCallbacks<List<Contact>>() {
#Override
public Loader<List<Contact>> onCreateLoader(int arg0, Bundle arg1) {
ContactPageLoader cpl = new ContactPageLoader(getActivity(), app);
cpl.setFilter(currentFilter);
return cpl;
}
#Override
public void onLoadFinished(Loader<List<Contact>> arg0, List<Contact> contacts) {
app.getAllContacts().subList(0, Math.min(app.getAllContacts().size() - 1, 3)));
allContacts.update(app.getAllContacts());
((SeparatedListAdapter) getListAdapter()).notifyDataSetInvalidated();
((SeparatedListAdapter) getListAdapter()).notifyDataSetChanged();
}
#Override
public void onLoaderReset(Loader<List<Contact>> arg0) {
}
};
private static class ContactAdapter extends ArrayAdapter<Contact> {
private LayoutInflater inflater;
public ContactAdapter(Context context) {
super(context, -1);
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void update(List<Contact> contacts) {
if (contacts == null) {
return;
}
setNotifyOnChange(false);
clear();
addAll(contacts);
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflate(getContext());
}
fill((ViewGroup) convertView, getItem(position));
return convertView;
}
private View inflate(Context context) {
View convertView = inflater.inflate(R.layout.contact_row, null, false);
convertView.setTag(R.id.contact_avatar, convertView.findViewById(R.id.contact_avatar));
convertView.setTag(R.id.contact_name, convertView.findViewById(R.id.contact_name));
convertView.setTag(R.id.contact_info, convertView.findViewById(R.id.contact_info));
return convertView;
}
private static void fill(ViewGroup rl, Contact contact) {
fillTextView(rl, R.id.contact_name, contact.getName());
fillTextView(rl, R.id.contact_info, contact.getInfo());
}
private static void fillTextView(ViewGroup rl, int id, String description) {
TextView t = ((TextView) rl.getTag(id));
t.setText(description);
}
}
public static class ContactPageLoader extends AsyncTaskLoader<List<Contact>> {
private SumaApplication app;
private String filter = null;
public ContactPageLoader(Context context, SumaApplication app) {
super(context);
this.app = app;
}
public void setFilter(String filter) {
this.filter = filter;
}
#Override
public List<Contact> loadInBackground() {
List<Contact> temp = new ArrayList<Contact>();
for(Contact c : app.getAllContacts()){
if(c.getName().matches("(.*)"+filter+"(.*)")){
temp.add(c);
}
}
return temp;
}
#Override
protected void onStartLoading() {
super.onStartLoading();
forceLoad();
}
}
private String currentFilter = null;
private OnQueryTextListener queryListener = new OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
// Called when the action bar search text has changed. Update
// the search filter, and restart the loader to do a new query
// with this filter.
String newFilter = newText;
// Don't do anything if the filter hasn't actually changed.
// Prevents restarting the loader when restoring state.
if (currentFilter == null && newFilter == null) {
return true;
}
if (currentFilter != null && currentFilter.equals(newFilter)) {
return true;
}
currentFilter = newFilter;
getLoaderManager().restartLoader(0, null, loaderCallbak);
return true;
}
};
private static class SearchViewImpl extends SearchView {
public SearchViewImpl(Context context) {
super(context);
}
// The normal SearchView doesn't clear its search text when
// collapsed, so we will do this for it.
#Override
public void onActionViewCollapsed() {
setQuery("", false);
super.onActionViewCollapsed();
}
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawingCacheQuality="high"
android:orientation="vertical" >
<SearchView
android:id="#+id/contacts_to"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f1f1f1"
android:iconifiedByDefault="false"
android:paddingBottom="20dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="20dp"
android:queryHint="#string/query_hint"
android:visibility="visible"
android:/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f7f7f7"
android:orientation="vertical"
android:padding="20dp"
android:visibility="visible" >
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:divider="#color/separator_line"
android:dividerHeight="1dp" >
</ListView>
</LinearLayout>
Change the onCreateView like this.. Your using SearchView in your layout xml(not SearchViewImpl)
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_list_contacts, container, false);
searchView = (SearchView) v.findViewById(R.id.contacts_to);
searchView.setOnQueryTextListener(queryListener);
searchView.setOnCloseListener(closeListener);
searchView.setIconifiedByDefault(true);
return v;
}
private LoaderCallbacks<List<Contact>> loaderCallbak = new LoaderCallbacks<List<Contact>>() {
#Override
public Loader<List<Contact>> onCreateLoader(int arg0, Bundle arg1) {
ContactPageLoader cpl = new ContactPageLoader(getActivity(), app);
cpl.setFilter(currentFilter);
return cpl;
}
#Override
public void onLoadFinished(Loader<List<Contact>> arg0, List<Contact> contacts) {
if(currentFilter == null){
allContacts.update(app.getAllContacts());
} else{
allContacts.update(temp);
}
((SeparatedListAdapter) getListAdapter()).notifyDataSetInvalidated();
((SeparatedListAdapter) getListAdapter()).notifyDataSetChanged();
}