Android list view current position doesn't work properly - android

I'm Getting data from my database and pushing them into ListView to view all the data.
Inside my ListView I also have a TextView with the text "Like" in it. Now when I click the like text it will change to "Liked" and I'm updating my like status in my database.
Now my problem is that when i click the "Like" text, the text changes to "Liked" and also it is updated in DB. But also when I scroll through the List View, I can notice other lists' Like text is also changed to Liked. I'm not sure what's going wrong.
I've been trying to get around this problem for quite some days but had no success.
This is my adapter code. At the bottom you can see my onClickListener for the textview
package com.mytestapp.myapp;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class ForumAdapter extends ArrayAdapter<DiscussionList> {
private static List<DiscussionList> items = null;
public ForumAdapter(Context context, List<DiscussionList> items) {
super(context, R.layout.custom_list, items);
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
public static DiscussionList getModelPosition(int position) {
return items.get(position);
}
public void refill(List<DiscussionList> items) {
items.clear();
items.addAll(items);
notifyDataSetChanged();
}
public static class ViewHolder {
WebView mywebviewholder;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
View v = convertView;
if (v == null) {
LayoutInflater li = LayoutInflater.from(getContext());
v = li.inflate(R.layout.custom_list, null);
} else {
holder = (ViewHolder) convertView.getTag();
}
DiscussionList app = items.get(position);
if (app != null) {
TextView titleText = (TextView) v.findViewById(R.id.dscTitle);
TextView categoryText = (TextView) v.findViewById(R.id.dscCategory);
TextView descriptionText = (TextView) v
.findViewById(R.id.dscDescription);
TextView timeText = (TextView) v.findViewById(R.id.dscTime);
TextView idText = (TextView) v.findViewById(R.id.dscDiscId);
final TextView likeText = (TextView) v.findViewById(R.id.likeText1);
String like_Status = app.getLikeStatus();
titleText.setText(app.getTitle());
categoryText.setText(app.getCategory());
descriptionText.setText(app.getDescription());
timeText.setText(app.getTime());
idText.setText(app.getDiscId());
if (like_Status == "null") {
likeText.setText("Like");
} else {
likeText.setText("Liked");
}
final String dId = app.getDiscId();
// onClick for image button inside list view
likeText.setTag(new Integer(position));
likeText.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
final Integer myposition = (Integer) view.getTag();
// Toast.makeText(getContext(), "" + dId,
// Toast.LENGTH_SHORT)
// .show();
likeText.setText("Liked");
MainActivity val = new MainActivity();
val.updateLikeTable(dId);
}
});
}
return v;
}
}
And also this is my MainActivity.java file where i update the likes in database
package com.mytestapp.myapp;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Toast;
public class MainActivity extends ListActivity implements FetchDataListener {
public static String strTitle = "0", strCategory = "0",
strDescription = "0", strTime = "0", strDid = "0";
Collegemate_DB db = new Collegemate_DB(this);
int likeStatus = 1;
private ProgressDialog dialog;
public static String usId=null;
ImageButton imgButton;
List<DiscussionList> items = new ArrayList<DiscussionList>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list_forum_topics);
usId = db.getCurrentuserId();
initView();
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}
/*
* On click listener to get values from DiscussionList class and send it
* to another activity when clicking on the list item
*/
ListView forumList = getListView();
forumList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// Get position of the clicked list item from adapter
String dTitle, dCategory, dDescription, dTime, dDid;
DiscussionList accessVar = ForumAdapter
.getModelPosition(position);
dTitle = accessVar.getTitle();
dCategory = accessVar.getCategory();
dDescription = accessVar.getDescription();
dTime = accessVar.getTime();
dDid = accessVar.getDiscId();
/*
* Storing the forum values in string and passing it to another
* activity
*/
String values[] = { dTitle, dCategory, dDescription, dTime,
dDid };
Intent i = new Intent(MainActivity.this, ForumFullView.class);
i.putExtra("sendData", values);
startActivity(i);
}
});
}
private void initView() {
// show progress dialog
Log.i("j","Inside Init");
dialog = ProgressDialog.show(this, "", "Loading...");
String url = "http://example.com/mypath/listData.php?currentUser_id="
+ usId;
Log.i("Fetch Url : ", url);
FetchDataTask task = new FetchDataTask(this);
task.execute(url);
}
#Override
public void onFetchComplete(List<DiscussionList> data) {
// dismiss the progress dialog
if (dialog != null)
dialog.dismiss();
// create new adapter
ListView forumList = getListView();
// set the adapter to list
ForumAdapter adapter = new ForumAdapter(this, data);
if (forumList.getAdapter() == null) {
//final ForumAdapter adapter = new ForumAdapter(this, data);
forumList.setAdapter(adapter);
} else {
((ForumAdapter) forumList.getAdapter()).refill(items);
}
// setListAdapter(adapter);
}
#Override
public void onFetchFailure(String msg) {
// dismiss the progress dialog
if (dialog != null)
dialog.dismiss();
// show failure message
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
}
public void updateLikeTable(String dId,List<DiscussionList> items) {
try {
String likeUrl = "http://example.com/mypath/createlike.php?discId="
+ dId + "&userId=" + usId + "&like_status=" + likeStatus;
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet();
request.setURI(new URI(likeUrl));
client.execute(request);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Any help is appreciated.
Thanks in advance

The problem you're having is that the ListView widget recycles its views if it can. Once a view is off the screen from scrolling, it goes onto a garbage heap so that when a new view scrolls into place it can be reused, rather than requiring a fresh one to be inflated from scratch. That recycled view is the convertView parameter in the getView() method. When your ListView is first populating, convertView will always be null, since the garbage pile has nothing in it, so you're forced to inflate new views, but subsequent calls will likely have that parameter as non-null.
The practical result of this is that when a clicked view that's been set to "Liked" gets recycled, the TextView is still there and still populated with "Liked" rather than the presumed default of "Like". So if you click a view, then scroll down so it goes off the screen, it'll come back around and cause the bug you're seeing.
What you'll probably want to do to fix this is to set the text of likeText within getView() every time, based on what it is in your database. If the post has been liked, set it to "Liked", and if it hasn't, set it to "Like". It should just be one more line, assuming you have easy access to whether or not the post is liked from your DiscussionList object.
P.S. As a side note, hard-coded strings are typically frowned upon in Android, so you may want to move your "Liked" string into the resource files. It's not really necessary unless you're planning to do translations, but it's still good practice.

Related

How to add intent in viewpager

I want to add intent in sliding view pager. As I click different pages of the sliding view pager, a different activity must be called but I can't find the solution.
I have added image text and description in the view pager and a button is there in the layout
I think this would involve the use of page selected but earlier when I used onpageselected by using the position it opens up the page even if we are not clicking but I want to use intent here.
Adapterclass
package com.android.msahakyan.expandablenavigationdrawer.adapter;
import android.support.annotation.NonNull;
import android.support.v4.view.PagerAdapter;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.msahakyan.expandablenavigationdrawer.R;
import com.android.msahakyan.expandablenavigationdrawer.fragment.CardAdapter;
import com.android.msahakyan.expandablenavigationdrawer.fragment.CardItemString;
import java.util.ArrayList;
import java.util.List;
/**
* Created by tanis on 21-06-2018.
*/
public class CardPagerAdapterS extends PagerAdapter implements CardAdapter {
private List<CardView> mViews;
private List<CardItemString> mData;
private float mBaseElevation;
public CardPagerAdapterS() {
mData = new ArrayList<>();
mViews = new ArrayList<>();
}
public void addCardItemS(CardItemString item) {
mViews.add(null);
mData.add(item);
}
public float getBaseElevation() {
return mBaseElevation;
}
#Override
public CardView getCardViewAt(int position) {
return mViews.get(position);
}
#Override
public int getCount() {
return mData.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view = LayoutInflater.from(container.getContext())
.inflate(R.layout.adapter, container, false);
container.addView(view);
bind(mData.get(position), view);
CardView cardView = (CardView) view.findViewById(R.id.cardView);
if (mBaseElevation == 0) {
mBaseElevation = cardView.getCardElevation();
}
cardView.setMaxCardElevation(mBaseElevation * MAX_ELEVATION_FACTOR);
mViews.set(position, cardView);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
mViews.set(position, null);
}
private void bind(CardItemString item, View view) {
TextView titleTextView = (TextView) view.findViewById(R.id.titleTextView);
TextView contentTextView = (TextView) view.findViewById( R.id.contentTextView);
ImageView imageView=(ImageView) view.findViewById( R.id.image12 ) ;
titleTextView.setText(item.getTitle());
contentTextView.setText(item.getText());
imageView.setImageResource( item.getImages() );
}
}
FragmentAction
package com.android.msahakyan.expandablenavigationdrawer.fragment;
import android.content.Context;
import android.content.Intent;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.app.Fragment;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
//import android.support.v7.widget.LinearLayoutManager;
//import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import com.android.msahakyan.expandablenavigationdrawer.R;
import com.android.msahakyan.expandablenavigationdrawer.Registration;
import com.android.msahakyan.expandablenavigationdrawer.adapter.CardPagerAdapterS;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import in.goodiebag.carouselpicker.CarouselPicker;
import technolifestyle.com.imageslider.FlipperLayout;
import technolifestyle.com.imageslider.FlipperView;
/**
* A simple {#link Fragment} subclass.
* Use the {#link FragmentAction#newInstance} factory method to
* create an instance of this fragment.
*/
public class FragmentAction extends Fragment {
ViewPager mViewPager;
CardPagerAdapterS mCardAdapter;
ShadowTransformer mCardShadowTransformer;
private Context context;
ViewPager viewPager;
String titlesText [] = {" Website Design", " Digital Marketing", " Domain Registration", "Graphics Design", " Mobile Apps", " Server Hosting",
" Software Development", " Content Marketing", " Security (SSl)"};
String detailsArray [] = {
"Your website is your digital home. We create, design, redesign, develop, improvise, and implement. We make beautiful websites",
"We help your business reach potential customers on every possible digital device through all possible media channels ",
"To launch your website the first thing you need is the domain name. You can choose your domain name with us here ",
"We generate creative solutions and can create a wide range of graphic for your clients which match their business ",
"We are mobile. And we make you mobile. We make responsive websites and mobile apps which compliment your business ",
"When you are hosting your website in the India you will benefit from a higher ping rate and lowest latency ",
"Our team is competent at coding web apps with keen attention to detail & intuitive functionality that is high on design & creativity",
"Content is the heart of your digital presence. We create the right content with the right focus for your business",
"Secure your site with the world's leading provider of online security and get these exclusive features at no added cost",
};
int[] images = {R.drawable.website_design, R.drawable.digita,R.drawable.domain_registration,R.drawable.graphic,
R.drawable.mob,R.drawable.server,R.drawable.software_development,R.drawable.ontent,R.drawable.ssl};
private static final String KEY_MOVIE_TITLE = "key_title";
public FragmentAction() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment.
*
* #return A new instance of fragment FragmentAction.
*/
public static FragmentAction newInstance(String movieTitle) {
FragmentAction fragmentAction = new FragmentAction();
Bundle args = new Bundle();
args.putString(KEY_MOVIE_TITLE, movieTitle);
fragmentAction.setArguments(args);
return fragmentAction;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
View v = inflater.inflate(R.layout.fragment_action,container,false);
TextView txt = (TextView)v.findViewById( R.id.textView12 );
txt.setText("\u25BA Creative & Dedicated Team");
TextView txt1 = (TextView)v.findViewById( R.id.textView13 );
txt1.setText("\u25BA Affordable Cost");
TextView txt2 = (TextView)v.findViewById( R.id.textView14 );
txt2.setText("\u25BA Maintain Long Relationship");
TextView txt3 = (TextView)v.findViewById( R.id.textView15 );
txt3.setText("\u25BA Timely Deliverly ");
context = this.getContext();
mViewPager = (ViewPager)v.findViewById(R.id.viewpager1);
mCardAdapter = new CardPagerAdapterS();
for (int i=0; i<titlesText.length; i++){
mCardAdapter.addCardItemS(new CardItemString( titlesText[i], detailsArray[i],images[i]));
}
mCardShadowTransformer = new ShadowTransformer(mViewPager, mCardAdapter);
mViewPager.setAdapter(mCardAdapter);
mViewPager.setPageTransformer(false, mCardShadowTransformer);
mViewPager.setOffscreenPageLimit(3);
viewPager = (ViewPager)v.findViewById( R.id.viewpager );
ViewPagerAdapter viewPagerAdapter = new ViewPagerAdapter( this.getContext() );
viewPager.setAdapter( viewPagerAdapter );
Timer timer = new Timer( );
timer.scheduleAtFixedRate( new Mytime(),2000,4000 );
FloatingActionButton floatingActionButton = (FloatingActionButton)v.findViewById( R.id.floatingActionButton );
floatingActionButton.setOnClickListener( new View.OnClickListener() {
#Override
public void onClick(View view) {
startActivity( new Intent( getActivity(),Registration.class ) );
}
} );
return v;
}
public class Mytime extends TimerTask{
#Override
public void run() {
getActivity().runOnUiThread( new Runnable() {
#Override
public void run() {
if(viewPager.getCurrentItem() == 0) {
viewPager.setCurrentItem( 1 );
}
else if (viewPager.getCurrentItem()== 1){
viewPager.setCurrentItem( 2 );
}
else if (viewPager.getCurrentItem()== 2){
viewPager.setCurrentItem( 3 );
}
else if (viewPager.getCurrentItem()== 3){
viewPager.setCurrentItem( 4 );
}
else {
viewPager.setCurrentItem(0);
}
}
} );
}
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Drawable movieIcon = ResourcesCompat.getDrawable(getResources(), R.drawable.webdesign, getContext().getTheme());
String movieTitle = getArguments().getString(KEY_MOVIE_TITLE);
}
}
first of all onPageSelected listener is not really good idea in this case, because it is invoked every time when viewpager' current position changes (it's good for setting toolbar title, for example).
You can add another collection for Activities which can be invoked in CardPagerAdapterS, for example:
....
private List<CardItemString> mData;
private List<Class<? extends Activity> mActivities;
and use them to create click listener in order to open activities:
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view = LayoutInflater.from(container.getContext())
.inflate(R.layout.adapter, container, false);
container.addView(view);
bind(mData.get(position), view);
CardView cardView = (CardView) view.findViewById(R.id.cardView);
if (mBaseElevation == 0) {
mBaseElevation = cardView.getCardElevation();
}
cardView.setMaxCardElevation(mBaseElevation * MAX_ELEVATION_FACTOR);
cardView.setOnCLickListener(v-> {
context.startActivity(new Intent(context, mActivities.get(position));
});
mViews.set(position, cardView);
return view;
}

gridview custom adapter search

i have grid view , and custom adapter i want to search the items that are in the grid view by a search view ,,,
the thing is i don't know how to implement a search view along with a custom adopter ,, because i have a click event in the custom adapter which is when the user clicks an item it downloads a pdf file form internet ,, how can i add search view that will search the grid view items in with the custom adapter click even running ,
i am new usually i copy and paste the code i am 30% new .
this is my main activity
package com.alhaddadsoft.ammar.gridview;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.SearchView;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.GridView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
GridView gv;
GridView gv1;
TextView newtext;
Context context;
ArrayList prgmName;
public static String [] prgmNameList={"احمد عبده ماهر","احمد داوود","احمد صبحي منصور","لكشف الموروث اقرأ هذا أولا","الختان للذكور والاناث","الصادق النيهوم","الطريق إلى بيت المقدس","اوشو","بن فرناس","جمال البنا","جورج طرابيشي","زكريا اوزون", "سلامه موسى","سلسلة عندما نَطَقَ السراة","عبد الرزاق جبران","عبد الله القصيمي","علي الوردي","علي شريعتي","فاضل الربيعي","فرج فوده","كمال الصليبي","محمد اركون","محمد شحرور","محمد علي المحمود","محمود ابو ريه","نيازي عز الدين","هشام جعيط"
,"أبو الأعلى المودودي - الخلافة والملك","أسوار الصمت قراءة في الحقوق المدنية في السعودية لـ د. وليد الماجد","احمد امين - فجر الاسلام","اعمدة الحكمة السبعة . لورنس العرب","الارهابى ",
" الاسلام واصول الحكم -- على عبد الرازق","الاسلام وجراب الحاوي . شاكر النابلسي","الاضافة النوعية القرانية.مصطفى بوهندي",
"التأثير المسيحي في تفسير القران","التوراة اليهودية مكشوفة على حقيقتها","الخلافه الاسلاميه.محمد سعيد عشماوي","الدولة الاسلامية ،الجذور والتوحش عبدالباري عطوان","الدين واحتكار الحقيقه.واثق غازي","السادس من نوفمبر قيادة المراة للسيارة","السلطة في الاسلام لعبدالجواد حسين","السلفيون ايضا يدخلون النار.وليد طوغان","السنة بين الاصول والتاريخ ذويب رسالة دكتوراة","العقل الايماني","القران وثالوث الاستبداد.نشأت جعفر",
"القران ولغة السريان. احمد علي الجمل","اللاهوت العربى-يوسف زيدان","المؤمن الصادق - إيريك هوفر","الملوك المحتسبون حجم صغير","امي كاملة عقل ودين","انتكاسة المسلمين الى الوثنية - سيد القمني","بالداخل . اشرف فياض","بالداخل . اشرف فياض","تاريخ نجد . بن غنام مؤرخ محمد بن عبدالوهاب","تحرير المرأه من عهد الرساله","تزييف الاسلام.انور اسحاق","جغرافية التوراة _زياد منى","حتى لا يعود جهيمان . توما ... غهامر . ستيفان لاكروا",
"حكاية التدين السعودي . وحيد الغامدي","حواء والخطيئة","حوار حول القران وحده . محمد توفيق صدقي","رجم الزاني","طبائع الإستبداد ومصارع الإستعباد","عبد الرزاق عيد .. سدنة هياكل الوهم , نقد العقل الفقهي","عبيد بلا اغلال.تاريخ جزيرة العرب القريب","فتنة القول بتعليم البنات.عبدالله الوشمي","قدماء المصريين اول الموحدين","كارثة فلسطين . عبدالله التل","لعبة الامم","ما بعد الشيوخ ، انهيار ممالك الخليج","مابعد الصحوة.عبدالله الغذامي","مشكلة الحديث","معجزة اختيار اللفظ في القرآن",
"مقالة العبودية الطوعية","من يجرؤ على الكلام .بول فندلي","نقد الخطاب الديني لنصر ابو زيد","نقد الخطاب السلفي ابن تيمية نموذجا.رائد السمهوري","ورثة محمد .جذور الخلاف السني الشيعي"
};
public static int [] prgmImages={R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon,R.drawable.folder_mac_icon
,R.drawable.book1,R.drawable.book2,R.drawable.book3,R.drawable.book4,R.drawable.book5,R.drawable.book6,R.drawable.book7,R.drawable.book8,R.drawable.book9,R.drawable.book10,R.drawable.book11,R.drawable.book12,R.drawable.book13,R.drawable.book14,R.drawable.book15,R.drawable.book16,R.drawable.book17,R.drawable.book18,R.drawable.book19,R.drawable.book20,R.drawable.book21_,R.drawable.book21,R.drawable.book22,R.drawable.book23,R.drawable.book24,R.drawable.book25,R.drawable.book26,R.drawable.book27,R.drawable.book28,R.drawable.book29,R.drawable.book30,R.drawable.book31,R.drawable.book32,R.drawable.book33,R.drawable.book34,R.drawable.book35,R.drawable.book36_,R.drawable.book36,R.drawable.book37,R.drawable.book38,R.drawable.book39,R.drawable.book40,R.drawable.book41,R.drawable.book42,R.drawable.book43,R.drawable.book44,R.drawable.book45,R.drawable.book46,R.drawable.book47,R.drawable.book48,R.drawable.book49,R.drawable.book50,
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gv=(GridView) findViewById(R.id.gridView1);
gv.setAdapter(new CustomAdapter(this, prgmNameList, prgmImages));
}
public void openactivity1(){
edittext();
//Intent i = new Intent(this, AhmedDaod.class);
// startActivity(i);
}
public void edittext(){
// newtext = (TextView)findViewById(R.id.textView5);
// newtext.setText("hello");
}
}
This is my CustomAdapter acteivity
package com.alhaddadsoft.ammar.gridview;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class CustomAdapter extends BaseAdapter {
String[] result;
Context context;
int[] imageId;
private static LayoutInflater inflater = null;
String dwnload_file_path;
String file_name;
String imageViewD;
String textViewD;
GridView gridview;
public CustomAdapter(MainActivity mainActivity, String[] prgmNameList, int[] prgmImages ) {
// TODO Auto-generated constructor stub
result = prgmNameList;
context = mainActivity;
imageId = prgmImages;
inflater = (LayoutInflater) context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return result.length;
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public class Holder {
TextView tv;
ImageView img;
TextView edit ;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
final Holder holder = new Holder();
View rowView;
rowView = inflater.inflate(R.layout.programlist, null);
holder.tv = (TextView) rowView.findViewById(R.id.textView1);
holder.img = (ImageView) rowView.findViewById(R.id.imageView1);
holder.tv.setText(result[position]);
holder.img.setImageResource(imageId[position]);
rowView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
// Toast.makeText(context, "You Clicked " + result[position], Toast.LENGTH_LONG).show();
// String displayedText = ((TextView)((LinearLayout)myToast.getView()).getChildAt(0)).getText().toString();
try {
if (result[position].equals("أبو الأعلى المودودي - الخلافة والملك")) {
new AlertDialog.Builder(context)
.setTitle("تحميل الكتاب")
.setMessage("هل تريد تحميل الكتاب?")
.setPositiveButton("تحميل", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// continue with delete
dwnload_file_path = "http://www.jouhinabooks.com/get_file.php?id=470";
file_name = "book1.pdf";
imageViewD = "book1";
textViewD = result[position];
Downloadmethode();
}
})
.setNegativeButton("رجوع", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do nothing
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
//Intent intent= new Intent(context, AhmedDaod.class);
// intent.putextra("your_extra","your_class_value");
//context.startActivity(intent);
//MainActivity openactivity = new MainActivity();
// openactivity.openactivity1();
//edittext.setText("hello");
}
} catch (final Exception e) {
Toast.makeText(context, "error ", Toast.LENGTH_LONG).show();
}
}
});
return rowView;
}
public void Downloadmethode(){
Intent d = new Intent(context, DownloadBook.class);
d.putExtra("dwnload_file_path", dwnload_file_path);
d.putExtra("file_name", file_name);
d.putExtra("imageViewD",imageViewD);
d.putExtra("textViewD",textViewD);
context.startActivity(d);
}
}
This is how I implemented the search feature. Create two Lists, the searchList and the backUpList.
backUpList = loadMyData();
searchList.addAll(backUpList);
Now you have two lists that contain the same data. And because the lists contain only references to the objects there is no extra memory being used. Then feed the searchList to the adapter instead of the actual list.
adapter = new CustomAdapter(searchList*/,...other inputs*/);
gridView.setAdapter(adapter);
And now when you want to search in your data you empty your search list and search in you back up list. If an object should be shown then add it in your search list. Then notify the adapter and your search results are shown.
searchList.clear();
searchList.addAll(backUpList);
for(CustomObject object:backUpList){
if(meetsSearchCriteria(object)){
searchList.add(object);
}
}
adapter.notifyDataSetChanged();
And adjust the rest of your code to work with the searchList instead of the actual data list.
You must change your adapter to take an ArrayList of objects as input and not a table as your code shows. Tables do not support changes in their size after their creation.

How to assing an Image to Imageview based on a query results?

Good afternoon everyone,
I have a quick question. I have a query result that I store in a list/array and I am trying to display the appropriate image in the imageview. The query provides a name of the image that is stored in the resource folder(res/drawable). I am getting error syntax. I am not sure how to solve this issue. I have a database that stores the name of the image in a field (database) called spic.
I have tried this code:
how to work with images and database in android?
but it doesnt work in this class. I am not sure is it because this class is "extends ArrayAdapter {" instead of "extends Activity {"
here is my code:
zCustomUsersAdapter class:
package com.example.yao;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.drawable.Drawable;
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 zCustomUsersAdapter extends ArrayAdapter<YAOYVD> {
public zCustomUsersAdapter(Context context, List<YAOYVD> users) {
super(context, 0, users);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// Get the data item for this position
// User user = getItem(position);
YAOYVD user = getItem(position);
// Check if an existing view is being reused, otherwise inflate the view
if (convertView == null) {
convertView = LayoutInflater.from(getContext()).inflate(R.layout.zitem_user, parent, false);
}
// Lookup view for data population
TextView tvName = (TextView) convertView.findViewById(R.id.tvName);
TextView tvHome = (TextView) convertView.findViewById(R.id.tvHometown);
ImageView tvImage = (ImageView) convertView.findViewById(R.id.ivUserIcon);
// Populate the data into the template view using the data object
tvName.setText(String.valueOf(user.getID_YAO()));
//.name);
tvHome.setText(String.valueOf(user.getNAME_YAO()));
//.hometown);
// tvImage.setBackgroundResource( getResourceID (String.valueOf(user.getSPIC_YAO()), "drawable",getApplicationContext() ));
// Return the completed view to render on screen
tvImage.setBackgroundResource(user.getSPIC_YAO()); //getSpic_YAO this is string in the YAO class. getSpic_YAO retrive the name of the image in the drawable folder.
return convertView;
}
}
zCustomListActivity
package com.example.yao;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.database.SQLException;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
public class zCustomListActivity extends Activity {
private YAOGetDataSource2 datasource;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.zactivity_custom_list);
//calling the method to create the database from asset folder
copydbfromassest();
// datasource = new YAODeckListDataSource(this);
datasource = new YAOGetDataSource2(this);
datasource.open();
populateUsersList();
}
private void populateUsersList() {
// Construct the data source
//List<YAOYVD> values = datasource.SQLYVDTABLESEARCH();
List<YAOYVD> arrayOfUsers = datasource.SQLYVDTABLESEARCH();
//.getUsers();
// Create the adapter to convert the array to views
zCustomUsersAdapter adapter = new zCustomUsersAdapter(this, arrayOfUsers);
// Attach the adapter to a ListView
ListView listView = (ListView) findViewById(R.id.lvUsers);
listView.setAdapter(adapter);
}
//#Override
public void onClick(View view) {
// TODO Auto-generated method stub
}
//database open and close
#Override
protected void onResume() {
datasource.open();
super.onResume();
}
#Override
protected void onPause() {
datasource.close();
super.onPause();
}
#Override
protected void onDestroy(){
datasource.close();
super.onDestroy();
}
/****
* new things to considered
*/
///copy the database from assest folder
private void copydbfromassest() {
// TODO Auto-generated method stub
YAOMySQLiteHelper myhelper = new YAOMySQLiteHelper (this);
try{
//create datbase
myhelper.importIfNotExist();
}catch (IOException e){
throw new Error("Unable to Create the Database ");
}
try{
myhelper.openDataBase();
}catch (SQLException sqle){
throw sqle;
}
}
}
You need to retrieve the resource identifier associated with that image's name. For this, you will need to get your app's Resources, which requires a context.
Context ctx = getContext();
int resId = ctx.getResources().getIdentifier(user.getSPIC_YAO(), "drawable", ctx.getPackageName());
if(resId != 0){
tvImage.setBackgroundResource(resId);
}

Refreshing value at a list view when activity is re-opened back from another activity

I need your help to solve the following concern I have related to an activity.
An activity has a list view showing JSON objects. When the users taps on a row, another activity opens showing more details about the selected object. On this second activity, the user may click on a button to up vote the object. The amount of votes is then increased by one. Then, if the user goes back to the previous activity, the amount of given votes showed is not updated, but should be updated taking into account the vote given by the user.
At the first activity (list view) the number of votes field is given from a previous activity through an intent:
FIRST ACTIVITY CODE (LIST):
import java.util.ArrayList;
import java.util.HashMap;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
public class Empresas_ListViewAdapter extends BaseAdapter {
// Declare Variables
Context context;
LayoutInflater inflater;
ArrayList<HashMap<String, String>> data;
ImageLoader imageLoader;
HashMap<String, String> resultp = new HashMap<String, String>();
public Empresas_ListViewAdapter(Context context,
ArrayList<HashMap<String, String>> arraylist) {
this.context = context;
data = arraylist;
imageLoader = new ImageLoader(context);
}
#Override
public int getCount() {
return data.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
public View getView(final int position, View convertView, ViewGroup parent) {
// Declare Variables
TextView valoracionEmpresa;
TextView nombreEmpresa;
TextView direccionEmpresa;
ImageView strImagen;
TextView descripcionEmpresa;
TextView telefonoEmpresa;
TextView facebookEmpresa;
TextView emailEmpresa;
TextView textoOferta;
TextView horarioEmpresa;
TextView latitudEmpresa;
TextView longitudEmpresa;
TextView idEmpresa;
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View itemView = inflater.inflate(R.layout.empresas_listview_item, parent, false);
// Get the position
resultp = data.get(position);
// Locate the TextViews in listview_item.xml
valoracionEmpresa = (TextView) itemView.findViewById(R.id.valoracionEmpresa);
nombreEmpresa = (TextView) itemView.findViewById(R.id.nombreEmpresa);
direccionEmpresa = (TextView) itemView.findViewById(R.id.direccionEmpresa);
// Locate the ImageView in listview_item.xml
strImagen = (ImageView) itemView.findViewById(R.id.strImagen);
// Capture position and set results to the TextViews
valoracionEmpresa.setText(resultp.get(Empresas_MainActivity.VALORACIONEMPRESA));
nombreEmpresa.setText(resultp.get(Empresas_MainActivity.NOMBREEMPRESA));
direccionEmpresa.setText(resultp.get(Empresas_MainActivity.DIRECCIONEMPRESA));
// Capture position and set results to the ImageView
// Passes flag images URL into ImageLoader.class
imageLoader.DisplayImage(resultp.get(Empresas_MainActivity.STRIMAGEN), strImagen);
// Capture ListView item click
itemView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
// Get the position
resultp = data.get(position);
Intent intent = new Intent(context, Empresas_SingleItemView.class);
// Pass all data rank
intent.putExtra("valoracionEmpresa", resultp.get(Empresas_MainActivity.VALORACIONEMPRESA));
// Pass all data country
intent.putExtra("nombreEmpresa", resultp.get(Empresas_MainActivity.NOMBREEMPRESA));
// Pass all data population
intent.putExtra("direccionEmpresa",resultp.get(Empresas_MainActivity.DIRECCIONEMPRESA));
// Pass all data flag
intent.putExtra("strImagen", resultp.get(Empresas_MainActivity.STRIMAGEN));
intent.putExtra("descripcionEmpresa",resultp.get(Empresas_MainActivity.DESCRIPCIONEMPRESA));
intent.putExtra("telefonoEmpresa",resultp.get(Empresas_MainActivity.TELEFONOEMPRESA));
intent.putExtra("facebookEmpresa",resultp.get(Empresas_MainActivity.FACEBOOKEMPRESA));
intent.putExtra("emailEmpresa",resultp.get(Empresas_MainActivity.EMAILEMPRESA));
intent.putExtra("textoOferta",resultp.get(Empresas_MainActivity.TEXTOOFERTA));
intent.putExtra("horarioEmpresa",resultp.get(Empresas_MainActivity.HORARIOEMPRESA));
intent.putExtra("latitudEmpresa",resultp.get(Empresas_MainActivity.LATITUDEMPRESA));
intent.putExtra("longitudEmpresa",resultp.get(Empresas_MainActivity.LONGITUDEMPRESA));
intent.putExtra("idEmpresa",resultp.get(Empresas_MainActivity.IDEMPRESA));
// Start SingleItemView Class
context.startActivity(intent);
}
});
return itemView;
}
}
SECOND ACTIVITY CODE (DETAIL)
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.ByteArrayBuffer;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
public class Empresas_SingleItemView extends Activity {
// Declare Variables
String valoracionEmpresa;
String nombreEmpresa;
String direccionEmpresa;
String descripcionEmpresa;
String telefonoEmpresa;
String facebookEmpresa;
String emailEmpresa;
String textoOferta;
String horarioEmpresa;
String latitudEmpresa;
String longitudEmpresa;
String imagenstrImagen;
String idEmpresa;
String position;
private ProgressBar pb;
URL aURL;
/* Will be filled and displayed later. */
String aString = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the view from singleitemview.xml
ImageLoader imageLoader = new ImageLoader(this);
setContentView(R.layout.empresas_singleitemview);
Intent i = getIntent();
// Get the result of rank
valoracionEmpresa = i.getStringExtra("valoracionEmpresa");
// Get the result of country
nombreEmpresa = i.getStringExtra("nombreEmpresa");
// Get the result of population
direccionEmpresa = i.getStringExtra("direccionEmpresa");
descripcionEmpresa = i.getStringExtra("descripcionEmpresa");
telefonoEmpresa = i.getStringExtra("telefonoEmpresa");
facebookEmpresa = i.getStringExtra("facebookEmpresa");
emailEmpresa = i.getStringExtra("emailEmpresa");
textoOferta = i.getStringExtra("textoOferta");
horarioEmpresa = i.getStringExtra("horarioEmpresa");
latitudEmpresa = i.getStringExtra("latitudEmpresa");
longitudEmpresa = i.getStringExtra("longitudEmpresa");
idEmpresa = i.getStringExtra("idEmpresa");
// Get the result of flag
imagenstrImagen = i.getStringExtra("strImagen");
// Locate the TextViews in singleitemview.xml
TextView txtvaloracionempresa = (TextView) findViewById(R.id.valoracionEmpresa);
TextView txtnombreempresa = (TextView) findViewById(R.id.nombreEmpresa);
TextView txtdireccionempresa = (TextView) findViewById(R.id.direccionEmpresa);
TextView txtdescripcionempresa = (TextView) findViewById(R.id.descripcionEmpresa);
TextView txtofertaempresa = (TextView) findViewById(R.id.textoOferta);
TextView txthorarioempresa = (TextView) findViewById(R.id.horarioEmpresa);
// Locate the ImageView in singleitemview.xml
ImageView imagenEmpresa = (ImageView) findViewById(R.id.strImagen);
// Set results to the TextViews
txtvaloracionempresa.setText(valoracionEmpresa);
txtnombreempresa.setText(nombreEmpresa);
txtdireccionempresa.setText(direccionEmpresa);
txtdescripcionempresa.setText(descripcionEmpresa);
txtofertaempresa.setText(textoOferta);
txthorarioempresa.setText(horarioEmpresa);
// Capture position and set results to the ImageView
// Passes flag images URL into ImageLoader.class
imageLoader.DisplayImage(imagenstrImagen, imagenEmpresa);
}
public void openFacebook(View view)
{
String url = "http://es-es.facebook.com/pages/"+facebookEmpresa;
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
public void openEmail(View view)
{
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("message/rfc822");
i.putExtra(Intent.EXTRA_EMAIL , new String[]{emailEmpresa});
i.putExtra(Intent.EXTRA_SUBJECT, "Email desde Vive Gran Canaria App");
i.putExtra(Intent.EXTRA_TEXT , "Escribe aqui el texto de tu mensaje");
try {
startActivity(Intent.createChooser(i, "Send mail..."));
} catch (android.content.ActivityNotFoundException ex) {
Toast.makeText(Empresas_SingleItemView.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
}
}
public void openLlamar(View view)
{
try {
Intent callIntent = new Intent(Intent.ACTION_CALL);
callIntent.setData(Uri.parse("tel:"+telefonoEmpresa));
startActivity(callIntent);
} catch (ActivityNotFoundException e) {
Log.e("helloandroid dialing example", "Call failed", e);
}
}
public void openVotar(View view)
{
Log.i("Response", "Hemos entrado en openVotar: ");
ConnectionTask task = new ConnectionTask();
String[] params = new String[2];
String url = "http://XXXXX/cambiarvaloracionempresa.php?id="+idEmpresa;
params[0] = url;
//params[1] = somethingelseifneeded;
task.execute(params); }
private class ConnectionTask extends AsyncTask<String, Void, String>{
#Override
protected String doInBackground(String... urls) {
URL aURL;
/* Will be filled and displayed later. */
String aString = null;
try {
aURL = new URL(
urls[0]);
/* Open a connection to that URL. */
final HttpURLConnection aHttpURLConnection = (HttpURLConnection) aURL.openConnection();
/* Define InputStreams to read from the URLConnection. */
InputStream aInputStream = aHttpURLConnection.getInputStream();
BufferedInputStream aBufferedInputStream = new BufferedInputStream(
aInputStream);
/* Read bytes to the Buffer until there is nothing more to read(-1) */
ByteArrayBuffer aByteArrayBuffer = new ByteArrayBuffer(50);
int current = 0;
while ((current = aBufferedInputStream.read()) != -1) {
aByteArrayBuffer.append((byte) current);
}
/* Convert the Bytes read to a String. */
aString = new String(aByteArrayBuffer.toByteArray()); } catch (IOException e) {
// Log.d(TAG, e.toString());
}
return aString;
}
#Override
protected void onPostExecute(String result) {
TextView aTextView;Log.i("Response JSON", result);
TextView txtvaloracionempresa = (TextView) findViewById(R.id.valoracionEmpresa);
txtvaloracionempresa.setText(result);
// result is what you got from your connection
//aTextView.setText(result);
}
}
}
How could I refresh the number of votes on the first activity (list view) when the user goes back to it from the second activity (detail view)
You need to call notifyDataSetChanged() on your adapter in order to refresh the listview.
adapter.notifyDataSetChanged() should be called after every change in your datset.
If you are doing it in say a for loop the
for (int i = ; ; ){
…
…
adapter.addItem(item);
adapter.notifyDataSetChanged();
}
otherwise you can call it after the loop.
Also, notifyDataSetChanged() should be called from the UI thread
Check out http://developer.android.com/reference/android/widget/BaseAdapter.html#notifyDataSetChanged()
Also, this is a very helpful video
https://www.youtube.com/watch?v=wDBM6wVEO70&t=17m38s

Out-of-sync ArrayAdapter with Autocomplete

I have 3 classes, I wish to use the autocomplete text box to show user certain data (aka cities) from a web service (rest api). I've used this implementation on various features of my own application, but for some reason, there's a synchronization problem within the textchangedlistener...
CitiesArrayAdapter.java (to show a different view, in my case the "city, state"):
package com.android.lzgo.adapters;
import java.util.ArrayList;
import java.util.List;
import com.android.lzgo.activities.LiftSearchActivity;
import com.android.lzgo.activities.R;
import com.android.lzgo.models.City;
import com.android.lzgo.models.Lift;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
public class CitiesArrayAdapter extends ArrayAdapter<City> {
private static final String TAG = CitiesArrayAdapter.class.getName();
private final ArrayList<City> cities;
private int viewResourceId;
public CitiesArrayAdapter(Context context, int textViewResourceId, ArrayList<City> results) {
super(context, textViewResourceId, results);
this.cities = results;
this.viewResourceId = textViewResourceId;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
// assign the view we are converting to a local variable
View v = convertView;
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(viewResourceId, null);
}
City i = cities.get(position);
Log.d(TAG, "Here is my value: " + i);
if (i != null) {
TextView tt = (TextView) v.findViewById(android.R.id.text1);
Log.d(TAG, "Name: " + i.getName() + ", " + i.getProvince_name());
if (tt != null){
tt.setText("Name: " + i.getName() + ", " + i.getProvince_name());
}
}
// the view must be returned to our activity
return v;
}
}
CitiesResponderFragment.java (this is how I get my values from my rest api):
package com.android.lzgo.fragment;
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import com.android.lzgo.activities.LiftSearchActivity;
import com.android.lzgo.definitions.Constants;
import com.android.lzgo.models.City;
import com.android.lzgo.service.LzgoService;
import com.google.gson.Gson;
import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.widget.ArrayAdapter;
import android.widget.Toast;
public class CitiesResponderFragment extends LzgoResponderFragment {
private static String TAG = CitiesResponderFragment.class.getName();
private List<City> mCities;
ArrayAdapter<City> adapter;
private String enteredCharacters;
LiftSearchActivity activity;
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
activity = (LiftSearchActivity) getActivity();
// This gets called each time our Activity has finished creating itself.
getCities();
}
private void getCities() {
if (mCities == null && activity != null) {
Intent intent = new Intent(activity, LzgoService.class);
intent.setData(Uri.parse(Constants.REST_CITIES_AUTOCOMPLETE));
Bundle params = new Bundle();
params.putString("search", getenteredCharacters());
intent.putExtra(LzgoService.EXTRA_HTTP_VERB, LzgoService.GET);
intent.putExtra(LzgoService.EXTRA_PARAMS, params);
intent.putExtra(LzgoService.EXTRA_RESULT_RECEIVER, getResultReceiver());
// Here we send our Intent to our RESTService.
activity.startService(intent);
}
}
#Override
public void onRESTResult(int code, String result) {
Log.e(TAG, Integer.toString(code));
Log.e(TAG, result);
// Check to see if we got an HTTP 200 code and have some data.
if (code == 200 && result != null) {
mCities = getCitiessFromJson(result);
adapter = activity.getArrayAdapter();
adapter.clear();
for( City city : mCities){
//debugging
Log.d(TAG, "City : " + city.getName());
adapter.add(city);
adapter.notifyDataSetChanged();
}
getCities();
}
else {
Activity activity = getActivity();
if (activity != null && code == 400) {
Toast.makeText(activity, result, Toast.LENGTH_SHORT).show();
}
else
Toast.makeText(activity, "Failed to load lzgo data. Check your internet settings.", Toast.LENGTH_SHORT).show();
}
}
private List<City> getCitiessFromJson(String json) {
ArrayList<City> cityList = new ArrayList<City>();
Gson gson = new Gson();
try {
JSONObject citiesWrapper = (JSONObject) new JSONTokener(json).nextValue();
JSONArray cities = citiesWrapper.getJSONArray("cities");
for (int i = 0; i < cities.length(); i++) {
//JSONObject city = cities.getJSONObject(i);
String jsonCity = cities.getString(i);
City city = gson.fromJson( jsonCity, City.class );
//Log.e(TAG, "Hurray! Parsed json:" + city.getString("name"));
//cityList.add(city.getString("name"));
cityList.add(city);
}
}
catch (JSONException e) {
Log.e(TAG, "Failed to parse JSON.", e);
}
return cityList;
}
public String getenteredCharacters() {
return enteredCharacters;
}
public void setenteredCharacters(String characters) {
this.enteredCharacters = characters;
}
}
LiftSearchActivity.java (My FragmentActivity):
package com.android.lzgo.activities;
import java.util.ArrayList;
import com.android.lzgo.adapters.CitiesArrayAdapter;
import com.android.lzgo.fragment.CitiesResponderFragment;
import com.android.lzgo.models.City;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.AutoCompleteTextView;
import android.widget.DatePicker;
public class LiftSearchActivity extends FragmentActivity{
private static final String TAG = LiftSearchActivity.class.getName();
// User lift input
private AutoCompleteTextView autoCityFrom;
private AutoCompleteTextView autoCityTo;
private DatePicker date;
private CitiesArrayAdapter adapter;
private ArrayList<City> mCities ;
int year , month , day;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.lift_search);
mCities = new ArrayList<City>();
adapter = new CitiesArrayAdapter(this,
android.R.layout.simple_dropdown_item_1line, mCities);
autoCityFrom = (AutoCompleteTextView) findViewById(R.id.cityFrom);
autoCityTo = (AutoCompleteTextView) findViewById(R.id.cityTo);
adapter.setNotifyOnChange(true);
autoCityFrom.setAdapter(adapter);
autoCityTo.setAdapter(adapter);
autoCityFrom.addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// no need to do anything
}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (((AutoCompleteTextView) autoCityFrom).isPerformingCompletion()) {
return;
}
if (charSequence.length() < 2) {
return;
}
String query = charSequence.toString();
getCities(query);
}
public void afterTextChanged(Editable editable) {
}
});
autoCityTo.addTextChangedListener(new TextWatcher() {
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
// no need to do anything
}
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (((AutoCompleteTextView) autoCityTo).isPerformingCompletion()) {
return;
}
if (charSequence.length() < 2) {
return;
}
String query = charSequence.toString();
getCities(query);
}
public void afterTextChanged(Editable editable) {
}
});
date = (DatePicker) findViewById(R.id.dpResult);
}
public void searchLifts(View view) {
Intent intent = new Intent(this, LiftsResultActivity.class);
//While autocomplete doesn't work hardcore value...
intent.putExtra("from", Integer.toString(9357)); // Sherbrooke
intent.putExtra("to", Integer.toString(6193)); // Montreal
intent.putExtra("date", Integer.toString(date.getMonth()+1) + "-" + Integer.toString(date.getDayOfMonth()) + "-" + Integer.toString(date.getYear()));
startActivity(intent);
}
public void getCities(String query) {
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
CitiesResponderFragment responder = (CitiesResponderFragment) fm.findFragmentByTag("RESTResponder");
responder = new CitiesResponderFragment();
responder.setenteredCharacters(query);
ft.add(responder, "RESTResponder");
ft.commit();
}
public CitiesArrayAdapter getArrayAdapter() {
// TODO Auto-generated method stub
return adapter;
}
}
I get the correct result and all. But my service doesn't seem to populate my array adapter in my activity, when I try to show my first "city", my adapter contains nothing. I wonder if I have to put a notifydatasetchanged (I tried, but doesn't work). I'm kind of confuse... any pointers?
While debugging the application I noticed that the properties mObjects of
the ArrayAdapter is cleared even if the associated ArrayList has
elements, and then properties mOriginalValues is filled with the
Strings loaded the first time.
Without seeing the full code base(+ data), I don't know if someone can pin point the reason for your code's failure. But I think the problem comes more from the way you setup the whole auto complete related code than some obvious line error. Below I'll try to address some of this issues(from my point of view) :
First of all, in the TextWatcher from LiftSearchActivity you call the getCities() method which adds, each time the user modifies the auto complete text, a Fragment to the Activity. I really doubt you want this, you should probably look at having only one Fragment in the Activity on which to call a refresh(or update) method, passing it the new filter text. If the user rotates the phone those fragments will also be recreated because of the configuration change.
Second, in the CitiesResponderFragment class you call the fragment's getCities() method(if you don't have any data) in onActivityCreated which start an update service(?!). Now related to the first point, you could end up doing a lot of unnecessary queries, for example if the user enter 4 characters and then decides to delete one of the characters as it was incorrect you'll end up with 5 added fragments, from which 3 will make the service start/query for data.
And last, I'm not sure if you understand how the AutoCompleteTextView works under the hood. In order to provide the drop down with the suggestions the AutoCompleteTextView widget will filter its adapter(adapter.getFilter()) and show as suggestions the items that match the filter. I don't know if you set some threshold on the AutoCompleteTextView but initially the auto complete will be empty for the first 3 characters entered as you start with an empty list of items when you first setup the Activity. The first two characters will not show anything because you start with an empty list and you don't add any new fragments(charSequence.length() < 2). The third character will most likely also not show anything, because the overhead of creating the fragment, starting the service and fetching the data will almost for sure be greater then doing the work of the adapter filtering(which will still see the initially empty list). I don't know if you tested, but from this fourth character the adapter should have some elements in it and the filtering should show something. Clearing the adapter and adding new data in it willl only make that data available to the next character entered in the AutoCompleteTextView.
The proper way of doing the filtering would be to further extend your adapter and implement the getFilter() method to return your own Filter implementation which would query the data store for new filtered items. The filtering method runs on a background thread, with a little work I think you could implement your current logic with the Service and the REST callback.
See example of the REST API Autocomplete : https://subversion.assembla.com/svn/rockitsearch-android/
Although it is part of my service, it can also serve as an example of how you can integrate your own REST API in AutoCompleteTextView control. If you are interested in autocomplete 3rd party service, here you go : www.rockitsearch.com

Categories

Resources