I'm trying to use MVVM with databinding .. Where should I write click event (Viewmodel Or Activity)
Examples are welcome...
You can write your click events on either. Personally, my preference depends on what I want to achieve and what I need to achieve it.
Click event in ViewModel
Define your ViewModel. Communicate with your activity via a Callback.
public class MyViewModel extends ViewModel{
private MyCustomCallback callback;
...
public void doOnClick(MyCustomCallback mCallback){
boolean isSuccessful = doMyAction.execute();
if (isSuccessful){
mCallback.actionIsSuccessful();
} else {
mCallback.actionFailed();
}
}
...
public void setCallback(callback){
this.callback = callback;
}
public MyCustomCallback getCallback(){
return this.callback;
}
...
public interface MyCustomCallback{
void actionIsSuccessful();
void actionFailed();
}
}
Implement this callback in your activity:
public class MyActivity extends AppCompatActivity{
...
private MyCustomCallback callback;
#Override
protected void onCreate(Bundle savedInstanceState){
...
callback = new MyViewModel.MyCustomCallback{
#Override
public void actionIsSuccessful(){
//do something when action is successful
}
#Override
public void actionFailed(){
//do something when action fails
}
}
viewModel.setCallback(callback);
}
}
Pass your ViewModel as a variable to your XML. Then do this:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/button_background"
android:layout_margin="20dp"
tools:text="CLICK ME!!!"
android:textColor="#android:color/white"
android:onClick="#{() -> ViewModel.doOnClick(ViewModel.callback)}"/>
Click events in Activity
public class MyActivity extends AppCompatActivity{
...
private MyCustomCallback callback;
#Override
protected void onCreate(Bundle savedInstanceState){
//initialize your binding
...
binding.setClickHandler(new MyActivityClickHandler());
}
public class MyActivityClickHandler{
public void onClickMeClicked(View view){
//do something
}
}
}
Then in your XML:
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/button_background"
android:layout_margin="20dp"
android:text="#string/verify"
android:textColor="#android:color/white"
android:onClick="#{ClickHandler::onClickMeClicked}"/>
For more information check the official doc here
Related
I am having the following xml
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/to_textedit"
android:onClick="#{() -> viewModel.openTimePickerClicked()}"
android:layout_width="match_parent"
android:text="10:00 pm"
android:textSize="14sp"
android:layout_height="match_parent"/>
and I am using view model to assign it is click listener as following
val openTimePickerClickEvent = LiveEvent<Unit>()
fun openTimePickerClicked() {
openTimePickerClickEvent.call()
}
and in my model I bind this observer as following
private val openTimePickerClicked = Observer<Unit> {
openTimePickerDialog () // here is the problem
}
private fun openTimePickerDialog(textInputEditText : TextInputEditText) {
val cal = Calendar.getInstance()
val timeSetListener = TimePickerDialog.OnTimeSetListener { timePicker, hour, minute ->
cal.set(Calendar.HOUR_OF_DAY, hour)
cal.set(Calendar.MINUTE, minute)
textInputEditText.setText(SimpleDateFormat("HH:mm").format(cal.time))
}
TimePickerDialog(
binding.root.context,
timeSetListener,
cal.get(Calendar.HOUR_OF_DAY),
cal.get(Calendar.MINUTE),
false
).show()
}
how can I path the view to my method in the view to be able to set the text of it
Yes, you can easily set the listener in a method which you have set in XML.
Please follow below steps:
Define callback/listener in ViewModel like below:
public class MyViewModel extends ViewModel{
private MyCustomCallback callback;
...
public void doOnClick(MyCustomCallback mCallback){
boolean isSuccessful = doMyAction.execute();
if (isSuccessful){
mCallback.actionIsSuccessful();
} else {
mCallback.actionFailed();
}
}
...
public void setCallback(callback){
this.callback = callback;
}
public MyCustomCallback getCallback(){
return this.callback;
}
...
public interface MyCustomCallback{
void actionIsSuccessful();
void actionFailed();
}}
Now you have set this listener/Callback in XML like below:
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/to_textedit"
android:onClick="#{() -> ViewModel.doOnClick(ViewModel.callback)}"
android:layout_width="match_parent"
android:text="10:00 pm"
android:textSize="14sp"
android:layout_height="match_parent"/>
Now You have to set listener in the main activity. like below:
public class MainActivity extends AppCompatActivity{
...
private MyCustomCallback callback;
#Override
protected void onCreate(Bundle savedInstanceState){
...
callback = new MyViewModel.MyCustomCallback{
#Override
public void actionIsSuccessful(){
//do something when action is successful
}
#Override
public void actionFailed(){
//do something when action fails
}
}
viewModel.setCallback(callback);
}
}
Hope! this code will help you.
Happy coding...
When I try to set the onClick method in my Google's SignInButton:
android:onClick="#{() -> viewModel.onGoogleLoginClick()}"
I always get this error:
Found data binding errors.
****/ data binding error ****msg:Cannot find the proper callback class for android:onClick. Tried android.view.View but it has 0 abstract
methods, should have 1 abstract methods.
file:/Users/user/Android/project/app/src/main/res/layout/activity_login.xml loc:53:31 - 53:66 ****\ data binding error ****
Here is my code:
activity_login.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".ui.login.LoginActivity">
<data>
<import type="android.view.View" />
<variable
name="viewModel"
type="com.example.myapp.ui.login.LoginViewModel" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="#dimen/default_layout_padding">
<EditText
android:id="#+id/login_name_editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/login_username_hint"
android:inputType="text"
android:text="#{viewModel.mEmail}" />
<EditText
android:id="#+id/login_pass_editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/login_name_editText"
android:hint="#string/login_password_hint"
android:inputType="numberPassword"
android:text="#{viewModel.mPassword}" />
<Button
android:id="#+id/login_login_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/login_pass_editText"
android:onClick="#{() -> viewModel.onServerLoginClick()}"
android:text="#string/login_login_button_text"
android:textAllCaps="true" />
<com.google.android.gms.common.SignInButton
android:id="#+id/login_google_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/login_login_button"
android:onClick="#{() -> viewModel.onGoogleLoginClick()}"/>
</RelativeLayout>
</layout>
LoginViewModel.class
public class LoginViewModel extends BaseViewModel<LoginNavigator> implements
GoogleApiClient.OnConnectionFailedListener, OnCompleteListener<GoogleSignInAccount>,
GoogleApiClient.ConnectionCallbacks {
private static final String LOG_TAG = LoginViewModel.class.getSimpleName();
public String mEmail;
public String mPassword;
public LoginViewModel(DataManager dataHelper, SchedulerProvider schedulerProviderHelper) {
super(dataHelper, schedulerProviderHelper);
}
public void onServerLoginClick() {
if (CommonUtils.loginDataIsCorrect(mEmail, mPassword)) {
doServerLogin(mEmail, mPassword);
} else {
getNavigator().handleError();
}
}
public void onGoogleLoginClick() {
getNavigator().googleLogin();
}
// Server
private void doServerLogin(String name, String pass) {
...
}
// Google
protected void doGoogleLogin(FragmentActivity fragmentActivity, Context context) {
...
}
...
}
LoginActivity.class
public class LoginActivity extends BaseActivity<ActivityLoginBinding, LoginViewModel> implements LoginNavigator {
private static final int REQUEST_CODE_REGISTER = 0;
private static final int REQUEST_CODE_GOOGLE_SIGN_IN = 1;
#BindString(R.string.login_data_missing_message)
String mDataMissingMessage;
#Inject
LoginViewModel mLoginViewModel;
private ActivityLoginBinding mActivityLoginBinding;
public static Intent newIntent(Context context) {
return new Intent(context, LoginActivity.class);
}
#Override
public int getBindingVariable() {
return BR.viewModel;
}
#Override
public int getLayoutId() {
return R.layout.activity_login;
}
#Override
public LoginViewModel getViewModel() {
return mLoginViewModel;
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
mActivityLoginBinding = getViewDataBinding();
mLoginViewModel.setNavigator(this);
mActivityLoginBinding.loginGoogleButton.setSize(SignInButton.SIZE_WIDE);
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_GOOGLE_SIGN_IN:
mLoginViewModel.handleGoogleSignInResult(data);
break;
}
super.onActivityResult(requestCode, resultCode, data);
}
#Override
public void googleLogin() {
mLoginViewModel.doGoogleLogin(this, this);
}
#Override
public void showGoogleForm(GoogleApiClient googleApiClient) {
Intent googleIntent = Auth.GoogleSignInApi.getSignInIntent(googleApiClient);
startActivityForResult(googleIntent, REQUEST_CODE_GOOGLE_SIGN_IN);
}
...
}
And the BaseActivity.class, where I bind view and data for each Activity:
public abstract class BaseActivity<T extends ViewDataBinding, V extends BaseViewModel> extends AppCompatActivity {
private T mViewDataBinding;
private V mViewModel;
public abstract int getBindingVariable();
#LayoutRes
public abstract int getLayoutId();
public T getViewDataBinding() {
return mViewDataBinding;
}
public abstract V getViewModel();
public void performDependencyInjection() {
AndroidInjection.inject(this);
}
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
performDependencyInjection();
super.onCreate(savedInstanceState);
performDataBinding();
}
#Override
protected void onResume() {
super.onResume();
}
private void performDataBinding() {
mViewDataBinding = DataBindingUtil.setContentView(this, getLayoutId());
this.mViewModel = mViewModel == null ? getViewModel() : mViewModel;
mViewDataBinding.setVariable(getBindingVariable(), mViewModel);
mViewDataBinding.executePendingBindings();
}
}
Does anyone know why this error? Because SignInButton implements OnClickListener. I have tried Invalidate Caches / Restart and deleting .gradle and .idea folders but is still not working.
Luckily, we've got #BindingAdapter to solve issues similar to this. Here's an example in Kotlin:
BindingAdapters.kt
#BindingAdapter("android:onClick")
fun bindSignInClick(button: SignInButton, method: () -> Unit) {
button.setOnClickListener { method.invoke() }
}
layout.xml
<com.google.android.gms.common.SignInButton
...
android:onClick="#{() -> viewModel.onSignInClick()}" />
It's a interesting question, since SignInButton extends View, but the doc states explicitly to register a listener with setOnClickListener(OnClickListener) in the class and not in the xml. Databinding wraps up the lamda expression as a listener (you can see that in the auto-generated data binding class) and probably it doesn't stick with the listener, which SignInButton is expecting. E.g. if you try to pass a View.OnClickListener variable via xml, you shouldn't get that compile error, but you probably also won't be able to receive your click events (like it's stated in the doc).
I am trying to create an app by using MVP design pattern. This is the first time i am using this pattern, thats the reason i am little concerned that either i am following the pattern correctly or not.
This is what i have done so far. I am not using Dagger2.
Interface
public interface MainActivityMVP {
interface Model{
void sendTokenToServer(MainActivityMVP.Presenter presenter);
}
interface View{
boolean isPnTokenRegistered();
void tokenUpdated();
void tokenFailedToUpdate();
}
interface Presenter{
void tokenUpdatedSuccessfully();
void tokenAlreadyExists();
void detachView();
}
On MainActivity, I have created an instance of Presenter and Model and pass the Model object to Presenter Constructor
MainActivity
public class MainActivity extends BaseActivity implements MainActivityMVP.View {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
mainPresenter= new MainPresenter(this, new MainModel());
mainPresenter.sendFCMTokenToServer();
}
On Presenter I call Model's method to perform operation, and pass presenter reference to it.
Presenter
public class MainPresenter implements MainActivityMVP.Presenter{
MainActivityMVP.View view;
MainActivityMVP.Model model;
public MainPresenter(MainActivityMVP.View view, MainActivityMVP.Model model){
this.view= view;
this.model= model;
}
public void sendFCMTokenToServer() {
model.sendTokenToServer(this);
}
#Override
public void tokenUpdatedSuccessfully() {
view.tokenUpdated();
}
#Override
public void tokenAlreadyExists() {
view.tokenFailedToUpdate();
}
In Model, I create instance of PreferenceManager class that gets data from SharedPreference
public class MainModel implements MainActivityMVP.Model {
PreferencesHelper preferencesHelper;
public MainModel(){
preferencesHelper= new PreferencesHelper();
}
#Override
public void sendTokenToServer(MainActivityMVP.Presenter presenter) {
if (preferencesHelper.getNotificationSettings().isEmpty()) {
//do stuff
presenter.tokenUpdatedSuccessfully();
}
}
Now i have these questions.
Is the above approach of implementing MVP pattern is fine, or i am
missing something here.
Is it fine if i add an other interface for call backs, or passing
Presenter to model is better approach, as i have seen some example
where they pass interactor reference to model.
Is it necessary to create Interactor Class in MVP pattern
Is it fine, and not against MVP rule if i create a separate
interface for Repository,
Developers have different varieties of implementing MVP. Few people use interactors. Its is not compulsory to use interactors in MVP. I will suggest you below since you are in a starting stage.
public interface MainView extends BaseView {
boolean isPnTokenRegistered();
void tokenUpdated();
void tokenFailedToUpdate();
}
Then have your basepresenter be like this
public interface BasePresenter<V extends BaseView> {
void setView(V view);
void destroyView();
void destroy();
}
Now your MainPresenter
public class MainPresenter implements BasePresenter<MainView>{
MainView view;
PreferencesHelper preferencesHelper;
MainPresenter(){
preferencesHelper= new PreferencesHelper();
}
#Override
public void setView(MainView view) {
this.view = view;
}
#Override
public void destroyView() {
this.view = null;
}
#Override
public void destroy() {
}
public void sendFCMTokenToServer() {
//Do whatever you want
}
}
Finally have your activity like this,
public class MainActivity extends BaseActivity implements MainView {
MainPresenter mainPresenter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
mainPresenter= new MainPresenter();
mainPresenter.attachView(this)
mainPresenter.sendFCMTokenToServer();
}
I am able to put data into Firebase database, but when I want to retrieve it and display it to ListView, it only displays blank screen.
BaseActivity class:
public class BaseActivity extends AppCompatActivity {
#Bean
OttoBus bus;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
bus.register(this);
}
#Override
protected void onDestroy() {
super.onDestroy();
bus.unregister(this);
}
}
HomeActivity class:
#OptionsMenu(R.menu.signout)
#EActivity(R.layout.activity_home)
public class HomeActivity extends BaseActivity {
private static final int LOGIN_REQUEST_CODE = 42;
#ViewById
ListView listView;
#Bean
ConversationAdapter conversationAdapter;
#Bean
UserDao userDao;
#AfterViews
void init() {
// if no user is logged in
if (FirebaseAuth.getInstance().getCurrentUser() == null) {
LoginActivity_.intent(this).startForResult(LOGIN_REQUEST_CODE);
} else {
userDao.init();
}
listView.setAdapter(conversationAdapter);
}
#OnActivityResult(value = LOGIN_REQUEST_CODE)
void loginSucceeded(int resultCode) {
if (resultCode != RESULT_OK) {
return;
}
userDao.init();
conversationAdapter.resetConversationFlow();
}
#Subscribe
public void usersLoaded(UsersLoadedEvent event) {
final FirebaseUser firebaseUser = FirebaseAuth
.getInstance().getCurrentUser();
if (userDao.userExists(firebaseUser.getUid())) {
userDao.setCurrentUser(userDao.getUserById(firebaseUser.getUid()));
} else {
final User user = new User(firebaseUser.getUid(),
firebaseUser.getDisplayName(),
firebaseUser.getPhotoUrl().toString());
userDao.write(user);
userDao.setCurrentUser(user);
}
}
#ItemClick
void listViewItemClicked(Conversation conversation) {
ConversationActivity_.intent(this)
.conversation(conversation)
.start();
}
/**
* When option item with id signOut is clicked.
*/
#OptionsItem
void signOut() {
FirebaseAuth.getInstance().signOut();
// restart this activity after user is logged out because if there is no user we will start
// login activity
final Intent intent = getIntent();
finish();
startActivity(intent);
}
/**
* Called when button with id=fab is clicked.
*/
#Click
void fab() {
CreateConversationActivity_.intent(this).start();
}
}
activity_home.xml
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="com.example.nemus.execomchatworkshop.activity.HomeActivity">
<ListView
android:id="#+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_margin="#dimen/large_margin"
android:src="#drawable/ic_add_black_24dp" />
</RelativeLayout>
ConversationItemView class:
#EViewGroup(R.layout.item_view_conversation)
public class ConversationItemView extends LinearLayout {
#ViewById
TextView title;
public ConversationItemView(Context context) {
super(context);
}
public void bind(Conversation conversation) {
title.setText(conversation.getTitle());
}
}
item_view_conversation.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<ImageView
android:id="#+id/conversationPhoto"
android:layout_width="#dimen/image_large_size"
android:layout_height="#dimen/image_large_size"
android:layout_margin="#dimen/medium_margin" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="#dimen/large_margin"
android:orientation="vertical">
<TextView
android:id="#+id/title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#color/primary_text"
android:textSize="#dimen/large_text" />
<TextView
android:id="#+id/conversationPreview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#color/secondary_text"
android:textSize="#dimen/medium_text" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
ConversationDao class
#EBean(scope = EBean.Scope.Singleton)
public class ConversationDao {
static final String CONVERSATION_TAG = "conversations";
private FirebaseDatabase database = FirebaseDatabase.getInstance();
private List<Conversation> conversations = new ArrayList<>();
private Map<String, Conversation> conversationMap = new HashMap<>();
#Bean
OttoBus bus;
/**
* After this class is injected call this method.
*/
#AfterInject
public void init() {
database.getReference(CONVERSATION_TAG).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
conversationMap = dataSnapshot.getValue(
new GenericTypeIndicator<Map<String, Conversation>>() {
});
publish();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
public void write(Conversation conversation) {
final DatabaseReference databaseReference =
database.getReference(CONVERSATION_TAG).push();
conversation.setId(databaseReference.getKey()); // set unique key to our conversation
databaseReference.setValue(conversation); // push conversation to database
}
public List<Conversation> getConversations() {
return conversations;
}
private void publish() {
conversations.clear();
if (conversationMap != null) {
conversations.addAll(conversationMap.values());
}
// post to event bus
bus.post(new ConversationsUpdateEvent());
}
ConversationAdapter class:
#EBean
public class ConversationAdapter extends BaseAdapter {
private List<Conversation> conversations = new ArrayList<>();
#RootContext
Context context;
#Bean
ConversationDao conversationDao;
#Bean
OttoBus bus;
/**
* This method is called after this class is injected.
*/
#AfterInject
void init() {
bus.register(this);
}
public void resetConversationFlow() {
conversationDao.init();
}
#Override
public int getCount() {
return conversations.size();
}
#Override
public Conversation getItem(int position) {
return conversations.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ConversationItemView conversationItemView;
if (convertView == null) { // if view item is not created
conversationItemView = ConversationItemView_.build(context);
} else { // if view item was already created
conversationItemView = (ConversationItemView) convertView;
}
// bind data to view
conversationItemView.bind(getItem(position));
return conversationItemView;
}
private void setConversations(List<Conversation> conversations) {
this.conversations = conversations;
// notify that data set changed so that the list is refreshed
notifyDataSetChanged();
}
#Subscribe
public void conversationsUpdated(ConversationsUpdateEvent event) {
setConversations(conversationDao.getConversations());
}
}
So, what am I missing here. Why is not displaying conversation title into ListView?
It's difficult to follow allow with all this code at once. You are more likely to get answers if you ask one small question, than one large one. This is what I would recommend for you to figure out how to solve this issue:
Get familiar with the Debugger. It is essential and once you learn it you will become much better at solving any issues and coding in general.
Setup breakpoints to stop after you've successfully retrieved your data. Then confirm that you actually received the data and it is currently stored in the variable you wish to use.
Now that you've confirmed that your data exists, make sure you're setting up the list view correctly.
Firstly, I would recommend you start out with RecylerView, as that is the much newer standard and has much more helpful tutorials online. They are fundamently the same thing but RecylerView is better. Then I would continue to use the debugger to check that my data is being passed in to the RecylerViewAdapter correctly, and that when the data is bounded, it is pointing it to the correct views.
Here is a good tutorial for using the Android studio debugger.
Here is a good tutorial by google for adding lists(Using recylerview)
I am developing small android application in which i created one class abc which extends LinearLayout and one activity xyz. Inside my class abc i define one interface in following manner
public class abc extends LinearLayout {
private OnclickxitemListener listener1;
public interface OnclickxitemListener
{
public String nil = "nilkash";
public void onclickxtitem();
}
public void setOnxitemSelectedListener(OnclickxitemListener listener)
{
this.listener1 = listener;
Log.i("#######################################", "inside set listener "+listener1);
}
public abc(Context context)
{
super(context);
}
#SuppressWarnings("deprecation")
public void initialiseImages()
{
create custome linear view here
ImageView image_View = (ImageView) parentLayout.findViewById(0);
image_View.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
String n = listener1.nil;
Log.i("#################################", "inside click"+n);
listener1.onclickxitem();
}
});
}
}
Now I tred to use this interface from my activity in following manner.
public class xyz extends Activity implements abc.OnclickxitemListener{
CustomviewActivity cubes;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
abc widget = new abc(this);
widget.setOnxitemSelectedListener(this);
cubes.initialiseImages();
}
#Override
public void onclickxitem() {
}
}
Now problem is that when I excuted image click listener in my class I am able to access variable value ("string nilkash") but I am not able to access method listener1.onclickxitem();. when i tried to acees that it gives me null pointer exception.
Whether I am doing anything wrong. How to solve this problem.
need help...
Thank you...
Ok I am really a little confused with your code. I would do something like this. If abc is my custom view in package com.test in my activity layout file xyz.xml
<com.test.abc
android:id="#+id/myview"
<!-- You can modify the values below the way you want -->
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_gravity="center"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"/>
In my abc class i would write something like this
public class abc extends ImageView{
private OnclickxitemListener listener;
public interface OnclickxitemListener
{
public String nil = "nilkash";
public void onclickxtitem();
}
public void setOnxitemSelectedListener(OnclickxitemListener l )
{
listener = l;
}
public abc(Context context, AttributeSet attrs)
{
super(context, attrs);
initialize();
}
public void initialize()
{
this.setImageResource(R.drawable.*name of the image saved in drawable*);
setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0)
{
// TODO Auto-generated method stub
notifyListener();
}
});
}
private void notifyListener()
{
if (null!=listener)
listener.onclickxtitem();
}
}
Finally in your activity xyz
public class xyz extends Activity {
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.xyz);
abc myview = (abc)findViewById(R.id.myview);
myview.setOnxitemSelectedListener(new abc.OnclickxitemListener()
{
#Override
public void onclickxtitem()
{
}
});
}
}
Based on the code you pasted in, your activity needs to implement OnclickxitemListener for your abc class to callback on. Remove the onclickxitem from your activity, implement the OnclickxitemListener and let your IDE implement the unimplemented onclickxitem method from the interface.
Calling cubes.initialiseImages(); will also give you a null pointer as cubes has not been initialised. Surely you want to be calling widget.initialiseImages()?
You are able to access the listener1.nil String as this has been declared and given a value.