Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have an activity that has container that contain fragments and this fragment has other fragments.
Now I want this second or child fragment to access views in main activity, but it returns null pointer exception.
class:
public class ImageListFragment extends AbsListViewBaseFragment implements ObservableScrollViewCallbacks {
public static final int INDEX = 0;
android.support.design.widget.FloatingActionButton mFab;
#Bind(R.id.ic_call)
ImageView mIcCall;
#Bind(R.id.ic_email)
ImageView mIcEmail;
#Bind(R.id.ic_forum)
ImageView mIcForum;
FabToolbar mFabToolbar;
ObservableListView mObservableListView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fr_image_list, container, false);
listView = (ListView) rootView.findViewById(android.R.id.list);
((ListView) listView).setAdapter(new ImageAdapter(getActivity()));
final SubTaB mainActivity = (SubTaB)getActivity();
ButterKnife.bind(mainActivity);
//////////////// problem here
mFabToolbar = (FabToolbar) rootView.findViewById(R.id.fabtoolbar);
////////////////
getFragmentManager().findFragmentByTag("TAG");
// rootView.findViewById(R.id.fab);
mObservableListView = (ObservableListView)rootView.findViewById(android.R.id.list);
//
mObservableListView.setAdapter(this.listView.getAdapter());
mObservableListView.setScrollViewCallbacks(this);
mainActivity.mFab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mainActivity.getApplicationContext(), "msg msg", Toast.LENGTH_LONG).show();
mainActivity.mFabToolbar.expandFab();
}
});
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
startImagePagerActivity(position);
}
});
return rootView;
}
#Override
public void onDestroy() {
super.onDestroy();
AnimateFirstDisplayListener.displayedImages.clear();
}
private static class ImageAdapter extends BaseAdapter {
private static final String[] IMAGE_URLS = Constants.IMAGES;
private LayoutInflater inflater;
private ImageLoadingListener animateFirstListener = new AnimateFirstDisplayListener();
private DisplayImageOptions options;
ImageAdapter(Context context) {
inflater = LayoutInflater.from(context);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(R.drawable.ic_stub) // تغيير الفيو قبل تحميل الصورة
.showImageForEmptyUri(R.drawable.ic_empty) // لما الصورة فاضية
.showImageOnFail(R.drawable.ic_error) // عند الفشل
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.displayer(new CircleBitmapDisplayer(Color.WHITE, 5))
.build();
}
#Override
public int getCount() {
return IMAGE_URLS.length;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = convertView;
final ViewHolder holder;
if (convertView == null) {
view = inflater.inflate(R.layout.item_list_image, parent, false);
holder = new ViewHolder();
holder.text = (TextView) view.findViewById(R.id.text);
holder.image = (ImageView) view.findViewById(R.id.image);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.text.setText("Item " + (position + 1));
ImageLoader.getInstance().displayImage(IMAGE_URLS[position], holder.image, options, animateFirstListener);
return view;
}
}
static class ViewHolder {
TextView text;
ImageView image;
}
#Override
public void onScrollChanged(int i, boolean b, boolean b1) {
}
#Override
public void onDownMotionEvent() {
}
#Override
public void onUpOrCancelMotionEvent(ScrollState scrollState) {
Log.d("","Scroll scroll scroll");
if (scrollState == ScrollState.UP) {
mFabToolbar.slideOutFab();
} else if (scrollState == ScrollState.DOWN) {
mFabToolbar.slideInFab();
}
}
#OnClick(R.id.fab)
void onFabClick() {
mFabToolbar.expandFab();
}
#OnClick(R.id.call)
void onClickCall() {
iconAnim(mIcCall);
}
#OnClick(R.id.ic_email)
void onClickEmail() {
iconAnim(mIcEmail);
}
#OnClick(R.id.ic_forum)
void onClickForum() {
iconAnim(mIcForum);
}
private void iconAnim(View icon) {
Animator iconAnim = ObjectAnimator.ofPropertyValuesHolder(
icon,
PropertyValuesHolder.ofFloat("scaleX", 1f, 1.5f, 1f),
PropertyValuesHolder.ofFloat("scaleY", 1f, 1.5f, 1f));
iconAnim.start();
}
private static class AnimateFirstDisplayListener extends SimpleImageLoadingListener {
static final List<String> displayedImages = Collections.synchronizedList(new LinkedList<String>());
#Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
if (loadedImage != null) {
ImageView imageView = (ImageView) view;
boolean firstDisplay = !displayedImages.contains(imageUri);
if (firstDisplay) {
FadeInBitmapDisplayer.animate(imageView, 500);
displayedImages.add(imageUri);
}
}
}
}
}
It is not good practise to find and control a view in this way. Views can easily become detached from activities and cause unexpected exceptions.
You should rather look at using callbacks to communicate between fragments and activities if required. That way, it also keeps your code in the correct places - so the activity is the only one touching its own views and the fragment also only touches its own views. It merely tells the activity (via callbacks) that something has happened that the activity might want to know about. It also ensures that the fragments are completely self contained and can be easily reused.
You can read about how to implement callbacks here: http://developer.android.com/training/basics/fragments/communicating.html
Use EventBus to communicate between the activity and the fragment. riggarro suggestion is the correct way. But you can also able to update the base activity views using the EventBus.
For example we need to update a TextView text in a activity from the fragment, follow the steps.
First you need to add the following library as dependency to your project in build.gradle of your app.
compile 'de.greenrobot:eventbus:2.4.0'
First you need to create a Event Object class to communicate between the fragment and activity like below.
public class UpdateTextEvent {
private String sampleTextValue;
public UpdateTextEvent(String textValue) {
this.sampleTextValue = textValue;
}
public String getTextValue() {
return sampleTextValue;
}
}
You need to post a event to the event bus in the fragment to update the TextView in the activity.
public class TestingFragment extends Fragment{
private EventBus bus = EventBus.getDefault()
public TextingFragment(){}
public void onCreate(Bundle onSavedInstanceState){
super.onCreate(onSavedInstanceState);
}
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState){
View v = inflater.inflate(R.layout.sample_activity, parent, false);
...
Button b1 = (Button) v.findViewById(R.id.button1);
b1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//trigger a update to the activity
bus.post(new UpdateTextEvent("testing"));
}
});
}
}
After that you need to register the bus with the callback of the event in the activity like below.
public class MainActivity extends Activity{
private EventBus bus = EventBus.getDefault();
private TextView textView;
#Override
public void onCreate(Bundle onSavedInstanceState){
super.onCreate(onSavedInstanceState);
....
// The textview going to be updated on posting the event
textView = (TextView) findViewById(R.id.text1);
bus.register(this);
}
public void onEvent(UpdateTextEvent event){
textView.setText(event.getTextValue());
}
}
In this above example the onEvent method will be called when you post a event from the fragment..
Hope it will help you.
Related
I've got a RecyclerView that needs to update in real-time when content is received. It successfully shows all the content at first load. When attempting to add a new item dynamically, it makes no difference. Is there anything I'm doing wrong here? Much appreciated!
MainActivity:
RecyclerView rvClips;
ClipboardRVAdapter adapter;
ArrayList<Clip> clips = new ArrayList<>();
private void SetupRV() {
adapter = new ClipboardRVAdapter(clips);
rvClips.setAdapter(adapter);
adapter.setClickListener(this);
rvClips.setLayoutManager(new LinearLayoutManager(getActivity()));
}
//this method gets called everytime a new item is received. I confirmed that it gets called.
public void OnNewClipReceived(Clip clip) {
clips.add(0, clip);
adapter.notifyItemInserted(0);
}
Adapter:
Standard adapter code. Simply shows all the items in the recyclerview.
public class ClipboardRVAdapter extends RecyclerView.Adapter<ClipboardRVAdapter.ViewHolder> {
private ItemClickListener mClickListener;
ArrayList<Clip> clips;
public ClipboardRVAdapter(ArrayList<Clip> clips) {
this.clips = clips;
}
public void setClickListener(ItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
public interface ItemClickListener {
void onItemClick(View view, int position);
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View contactView = inflater.inflate(R.layout.item_clipboard_clip, parent, false);
// Return a new holder instance
ViewHolder viewHolder = new ViewHolder(contactView);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Clip clip = clips.get(position);
holder.tvClipTitle.setText(clip.content);
}
#Override
public int getItemCount() {
return clips.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView tvClipTitle;
public ViewHolder(View itemView) {
super(itemView);
tvClipTitle = itemView.findViewById(R.id.tvClipTitle);
}
#Override
public void onClick(View view) {
if (mClickListener != null) mClickListener.onItemClick(view, getAdapterPosition());
}
}
}
Since you mentioned 'realtime', I'm guessing this could be a thread issue. Your code seems correct. It could be that the adapter needs to be refreshed in a runOnUiThread function. Try this:
public void OnNewClipReceived(Clip clip) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
clips.add(0, clip);
adapter.notifyItemInserted(0);
}
});
}
You would need this method in your RecyclerView adapter.
void addNewClip(Clip clip, int index) {
this.clips.add(index, clip);
notifyItemInserted(index);
}
Adding to clips(MainActivity's) won't make a difference because your adapter has it own ArrayList to work with.
I am using navigation component in my app I have 2 fragments one fragments list of items and another shows detail of an item when user clicks on an item in fragments 1 it goes to detail fragment and when I switch back to first fragment then all the listing duplicates again.
Below is my code:
CakeFragment.java
public class CakeFragment extends Fragment {
List<AllCakes> allCakeList = new ArrayList<>();
AllCakesAdapter adapter;
BottomNavigationView navView;
FragmentCakeBinding fragmentCakeBinding;
public CakeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
fragmentCakeBinding = FragmentCakeBinding.inflate(inflater,container,false);
navView = getActivity().findViewById(R.id.navView);
navView.setVisibility(View.GONE);
getAllCakes();
return fragmentCakeBinding.getRoot();
}
private void getAllCakes(){
Retrofit retrofit = RetrofitClient.getInstance();
ApiService apiService = retrofit.create(ApiService.class);
Call<List<AllCakes>> call = apiService.getAllCake();
call.enqueue(new Callback<List<AllCakes>>() {
#Override
public void onResponse(Call<List<AllCakes>> call, Response<List<AllCakes>> response) {
fragmentCakeBinding.cakeProgress.setVisibility(View.INVISIBLE);
fragmentCakeBinding.allCakeRecycler.setHasFixedSize(true);
fragmentCakeBinding.allCakeRecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
allCakeList.addAll(response.body());
adapter = new AllCakesAdapter(getActivity(),allCakeList);
fragmentCakeBinding.allCakeRecycler.setAdapter(adapter);
}
#Override
public void onFailure(Call<List<AllCakes>> call, Throwable t) {
fragmentCakeBinding.cakeProgress.setVisibility(View.INVISIBLE);
TastyToast.makeText(getActivity(),t.getMessage(),TastyToast.LENGTH_SHORT,TastyToast.ERROR).show();
}
});
}
}
AllCakesAdapter.java
public class AllCakesAdapter extends RecyclerView.Adapter<AllCakesAdapter.ViewHolder> {
Context context;
List<AllCakes> allCakeList;
public AllCakesAdapter(Context context, List<AllCakes> allCakeList) {
this.context = context;
this.allCakeList = allCakeList;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.allcakes_row,parent,false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
AllCakes model = allCakeList.get(position);
Glide.with(context).load(model.getImgurl()).into(holder.allCakeImg);
holder.allCakeName.setText(model.getName());
holder.cakeDisPrice.setPaintFlags(holder.cakeDisPrice.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
holder.moreCake.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
NavController navController = Navigation.findNavController((Activity) context,R.id.fragment);
navController.navigate(R.id.cakeDetailFragment);
}
});
}
#Override
public int getItemCount() {
return allCakeList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView allCakeImg;
Button moreCake;
TextView allCakeName;
public ViewHolder(#NonNull View itemView) {
super(itemView);
allCakeImg = itemView.findViewById(R.id.allCakeImg);
moreCake = itemView.findViewById(R.id.moreCake);
allCakeName = itemView.findViewById(R.id.allCakeName);
}
}
}
CakeDetailFragment.java
public class CakeDetailFragment extends Fragment {
FragmentCakeDetailBinding fragmentCakeDetailBinding;
public CakeDetailFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
fragmentCakeDetailBinding = FragmentCakeDetailBinding.inflate(inflater,container,false);
return fragmentCakeDetailBinding.getRoot();
}
}
Why is this happening?
private void getAllCakes(){
...
allCakeList.addAll(response.body());
adapter = new AllCakesAdapter(getActivity(),allCakeList);
fragmentCakeBinding.allCakeRecycler.setAdapter(adapter);
}
...
you're calling:
allCakeList.addAll(response.body());
every time without clearing your list out.
you have to clear that list:
allCakeList.clear();
allCakeList.addAll(response.body());
this is something you can easily determine yourself by just putting a breakpoint on your allCakeList to see what's inside it, if you haven't ever done this before, you should consider trying it out
Try the following and see if it solves your issue
CakeFragment.java
allCakeList.clear();
allCakeList.addAll(response.body());
//rest of the logic remains same
I want to use admob with recyclerview but there is a problem. I need to hide some elements that are belong to viewholder. I need to hide the imageview in which position the ImageView belongs. When i click holder.btnReklamIzle the picture in that position must be hid in onRewardedVideoAdLoaded method. How can i transmit the position to onRewardedVideoAdLoaded method?
public View onCreateView(#NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_kuponlar, container, false);
mRewardedVideoAd = MobileAds.getRewardedVideoAdInstance(KuponlarFragment.this.getActivity());
mRewardedVideoAd.setRewardedVideoAdListener(this);
tahminlerRecyclerView = root.findViewById(R.id.tahminlerRecyclerView);
linearLayoutManager = new LinearLayoutManager(this.getActivity());
tahminlerRecyclerView.setLayoutManager(linearLayoutManager);
tahminlerRecyclerView.setHasFixedSize(true);
loadRewardedVideoAd();
fetch();
return root;
}
private void loadRewardedVideoAd() {
mRewardedVideoAd.loadAd(getString(R.string.admob_ads_id),
new AdRequest.Builder().build());
}
private void fetch() {
Query query = FirebaseDatabase.getInstance()
.getReference()
.child("tahminler");
FirebaseRecyclerOptions<Mac> options =
new FirebaseRecyclerOptions.Builder<Mac>()
.setQuery(query, new SnapshotParser<Mac>() {
#NonNull
#Override
public Mac parseSnapshot(#NonNull DataSnapshot snapshot) {
return new Mac((double)snapshot.child("oran").getValue(),
snapshot.child("tahmin").getValue().toString(),
);
}
})
.build();
adapter = new FirebaseRecyclerAdapter<Mac, ViewHolder>(options) {
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.tahmin_tasarim_recyclerview, parent, false);
return new ViewHolder(view);
}
#Override
protected void onBindViewHolder(final ViewHolder holder, final int position, Mac mac) {
holder.btnReklamIzle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mRewardedVideoAd.isLoaded()) {
mRewardedVideoAd.show();
}
}});
}
};
tahminlerRecyclerView.setAdapter(adapter);
}
#Override
public void onRewardedVideoAdLoaded() {
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ImageView image;
public ViewHolder(View itemView) {
super(itemView);
image = itemView.findViewById(R.id.image);
}
}
onRewardedVideoAdLoaded is a callback method for an asynchronous operation hence you cannot pass values to it as arguments but use referenced variables.
For your case do the following:
Firstly
Create a global variable to hold the list of views to hide
ArrayList<View> views_to_hide = new ArrayList<>();
Secondly
Create a helper function to hide the views
function hideViews(ArrayList<View> views){
for(View v : views) v.setVisibility(View.GONE);
}
Thirdly
Inside onBindViewHolder Add to the list the views you want to hide under your button onClick
public void onClick(View v) {
//...
if (mRewardedVideoAd.isLoaded()) {
mRewardedVideoAd.show();
// Ads already shown you may want to manually hide other images here
}else{
// We only need to add to list when ads not loaded
// We also want to make sure we don't add same view to the list twice
if(!views_to_hide.contains(holder.image))
views_to_hide.add(holder.image);
}});
//...
Finally
Call your helper function inside onRewardedVideoAdLoaded
#Override
public void onRewardedVideoAdLoaded() {
//This hides the views that was added to the list before now
hideViews(views_to_hide);
}
I'm setting up an image adapter in my fragments. I recently learn the usefulness of Fragments and Therefore I am trying to switch from the traditional activities to a central activity with multiple fragments. But I cant get to display my images' infinite cycler view.
I have tried reading answers from previous questions here on Stack overflow (ImageAdapter cannot be applied to fragment class and ImageAdapter cannot be applied to a Fragment Class) but I didnt really understand anything perhaps because I am a beginner in android studio with no educational background in coding. I have also tried youtube and everywhere.
I havent found tutorials to do this, I understand that fragments is relatively new in android studio
This is the fragment I am trying to switch to
public TrendingFragment() {
// Required empty public constructor
}
private static final String TAG = "Trending";
HorizontalInfiniteCycleViewPager viewPager;
List<TrendingHolder> TrendingList = new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragme
View view = inflater.inflate(R.layout.fragment_trending, container, false);
initData();
viewPager = view.findViewById(R.id.view_pager);
viewPager.setAdapter(new TrendingAdapter(getActivity()));
return view;
}
private void initData() {
//Adding the Images on board
TrendingList.add(new TrendingHolder(R.drawable.ad_test));
TrendingList.add(new TrendingHolder(R.drawable.burger_test));
TrendingList.add(new TrendingHolder(R.drawable.italian_test));
TrendingList.add(new TrendingHolder(R.drawable.pizza_test));
}
}
This is my adapter class
public class TrendingAdapter extends PagerAdapter {
Context context;
List<TrendingHolder> TrendingList;
private static final String TAG = "TrendingAdapter";
public TrendingAdapter(Context context, List<TrendingHolder> trendingList) {
this.context = context;
this.TrendingList = trendingList;
}
#Override
public int getCount() {
return TrendingList.size();
}
#Override
public boolean isViewFromObject(View view, #NonNull Object o){
return view.equals(o);
}
#Override
public void destroyItem(#NonNull ViewGroup container, int position, #NonNull Object object) {
container.removeView((View)object);
}
#NonNull
#Override
public Object instantiateItem(#NonNull ViewGroup container, int position) {
//Inflate View
View view = LayoutInflater.from(context).inflate(R.layout.card_item, container, false);
//View
ImageView trending_image = (ImageView)view.findViewById(R.id.trending_holder);
//Set Data
trending_image.setImageResource(TrendingList.get(position).getImage());
//set On Event Click
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//shop activity comes here
Log.d(TAG, "onClick: added to Cart");
}
});
container.addView(view);
return view;
}
}
This is my model for the images
public class TrendingHolder {
private int image;
public TrendingHolder(){
}
public TrendingHolder(int image) {
this.image = image;
}
public int getImage() {
return image;
}
public void setImage(int image) {
this.image = image;
}
}
I am getting this error TrendingAdapter( )
in TrendingAdapter cannot be applied
to
(androidx.fragment.app.FragmentActivity) in my Trending Fragment
It seems like missing constructor parameter. The constructor of TrendingAdapter accepts 2 parameters public TrendingAdapter(Context context, List<TrendingHolder> trendingList). But you pass 1 parameter viewPager.setAdapter(new TrendingAdapter(getActivity()));.
I use ListActivity with SpecialAdapter that show some log information.
I do not use background thread but I get an error when scroll list:
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(16908298, class android.widget.ListView) with Adapter(class ru.FoxGSM.ui.DebugActivity$SpecialAdapter)]
Please, help me.
(FoxLog is static class that get log information, perhaps from another thread. But in list a want show FoxLog snapshot)
public class DebugActivity extends ListActivity {
private class SpecialAdapter extends BaseAdapter {
private LayoutInflater mInflater;
public SpecialAdapter(Context context) {
super();
// Cache the LayoutInflate to avoid asking for a new one each time.
mInflater = LayoutInflater.from(context);
}
public int getCount() {
return FoxLog.count();
}
public long getItemId(int index) {
return index;
}
public Object getItem(int index) {
return FoxLog.get(FoxLog.count()-index-1);
}
// Get the type of View
public View getView(int position, View convertView, ViewGroup parent) {
TextView text;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.debug_list, null);
text = (TextView)convertView.findViewById(R.id.text);
convertView.setTag(text);
} else
text = (TextView) convertView.getTag();
String s = (String) getItem(position);
if (s==null)
return convertView;
text.setText(s);
boolean isError = false;
if (s!=null && s.length()>0) {
String prefix = s.substring(0, 1);
if (prefix.equals("E") || prefix.equals("W"))
isError = true;
}
if (isError)
text.setBackgroundResource(R.color.red);
else
text.setBackgroundDrawable(null);
return convertView;
}
}
private void RefreshData() {
FoxLog.ReInit(this);
SpecialAdapter adapter = (SpecialAdapter)this.getListAdapter();
adapter.notifyDataSetChanged();
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.debug);
FoxLog.ReInit(this);
SpecialAdapter adapter = new SpecialAdapter(this);
setListAdapter(adapter);
Button mExit = (Button)findViewById(R.id.exit);
mExit.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
finish();
}
});
}
}