Accessing to a Textview from a class (not an activity) - android

I have a main activity that extends AppCompatActivity, this activity can easily access to the TextView, than I have another java class that I need to access to the same TextView... I couldn't find it out!

Check the code below:-
In your Activity :-
TextView txtview = (TextView)findviewbyId(R.id.tv);
MyJavaClass jav = new MyJavaClass();
jav.setTextView(txtview);
Now in your Java Class :-
class MyJavaClass {
TextView tv ;
public void setTextView(TextView view){
this.tv = view;
}
}

I think that it would be better to keep Android framework objects (especially those that extend Context (Views, Activities, Fragments, etc.) isolated from the rest of your code whenever possible.
Instead of exposing the TextView to your "plain" java object, it would be better to define an interface, devoid of Android Context, and pass that to your 'plain' java object.
Another effective strategy is to use a message bus (or RxJava subject acting as a bus), to communicate between the Activity containing the TextView and the plain java object. e.g. Let the plain java object tell the Activity to change the TextView's content via a message.

At first , why do you want to access a TextView from another class directly?
Is that class an Activity , Fragment or just a java class?
Although,
You can create a static TextView and you can access it in another class.
But be careful of activity lifecycle, if activity stopped so TextView's reference will be null.
Finally don't use static.
According to OOAD it's better to Don't pass TextView to another class.
Why my answer got -1 ?

Related

Can I declare a OnClickListener derived class and pass its instance to a view's setOnClickListener method in Frida

In Frida's hooking javascript file,Can I declare a new class which is derived from OnClickListener? I want to pass a new OnClickListener instance to an existing view's setOnClickListener method.
I can get a existing view class as below:
var viewCls = Java.use("com.xxx.myView");
This view does not have any onClickListener in original app. Would it be possible to attach a onClickListener instance to this view through Frida?
I know how to instance an existing class but I do not know how to declare a new class in Frida.
Thanks so much for your suggestion.
I did not find how to declare a new class in Frida. However, I found a workaround to get my requirement done. I share it here and hopefully can help those who met the same issue with me. Basically, what I want to do is to add a onClickListener for a existing View instance. Since we could not declare a new onClickListener derived class in Frida, we can declare it in a separate dex library file. In Frida, we can dynamic load this dex file, find the class, and then new it .The step is as below:
1, Create a java library with your own onClickListener derived class declared. For example:
package com.test.frida
class MyOnClickListener implements onClickListener {
public void onClick() {
//you code here
}
}
2, Compile it to a Android library file, which is assumed as mylib.dex. Then push it to android device.
3, In Frida, assuming the view you want to add onClickListener is appView. We first load mylib.dex as below:
var loader = Java.use("dalvik.system.DexClassLoader").$new(mylib_dex_path, optimizeDir, null, appView.getContext())
optimizeDir should be a directory belongs to the app. It is easy to find a one.
4, Get MyOnClickListener.class and new a instance for it.
Java.classFactory.loader = loader;
var myListenerCls = Java.classFactory.use("com.test.frida.MyOnClickListener");
var listenerObj = myListenerCls.$new();
5, Finally, pass this listener to appView
appView.setOnClickListener(listenerObj);

Why to use casting to instantiate views in android

Does anyone know the reason to cast when instantiating a view?
e.g.: TextView textView = (TextView) findViewById(R.id.textView);
That's because all views in android are subclasses of View class and findViewById does not know anything about the subclass, for instance you might have your own custom view. There is no way android would want to know about your view class, hence it just returns the superclass and you would have to manually typecast it to more specific implementation.
The reason for casting is because return type of findViewById() function in Android is View.
However, contrary to what #Bajji stated in his (currently accepted) answer, a function does have a mean to know about the type of View you are expecting to get and perform automatic casting to that class. Unfortunately, Android does not leverage this functionality...
The following function does that:
protected <T extends View> T findViewById(#IdRes int id) {
return (T) getRootView().findViewById(id);
}
If you would have this function defined, then you could do it this way:
TextView textView = findViewById(R.id.textView);
You can get a bit more info in this blog post.

Android - Correctly referencing and updating widgets and controls

Could someone explain the best way to achieve the following, I think it's a fairly simple question but I'd like to know the best way, as it can be achieved several different ways.
Let's say I wanted a class which updated a TextView's text to "Test". Of course this isn't what my real problem is, but I'm trying to make this question as simple as possible. Let's also say this will accept any text view.
The class it calls does not inherit Activity.
The ways I see to do this are as follows, please explain why and why not these methods should or shouldn't be used.
Pass the TextView as a reference and update the text.
public class Test
public void updateText(TextView tv)
{
tv.setText("Test");
}
The other option is to pass the Activity, and call findViewById, but the problem here is if the ID does not match that that the Test class expects, the view will return null and won't update the TextView.
public class Test
public void updateText(Activity act)
{
TextView tv = (TextView) act.findViewById(R.id.i_must_exist);
tv.setText("Test");
}
Another choice would be to use getters/setters.
public class Test
private TextView mTvToUpdate;
public void setTextView(TextView tv)
{
mTvToUpdate = tv;
}
public void updateText(Activity act)
{
mTvToUpdate.setText("Test");
}
I guess the real question is it wrong to pass an objects reference as a parameter, is Activity the preferred way? Why? It is more likely to experience memory leaks, are both solutions OK? Is it down to preference?
Please don't reply with "Why would you want to do this?" as in this example I obviously wouldn't want to do what I am asking, but the question behind it still applies.
Thanks in advance.
I wouldn't go with the last way without a good reason because when you hold a reference to an UI element, you may leak memory more easily. When you hold a reference to a Widget, you hold a reference to the Activity either, so you have to make sure that you don't hold the reference to the Widget if the Activity is destroyed (possibly with a WeakReference). This is described in the article Avoiding Memory Leaks.
Besides that there's no real difference.
The object which "owns" the textfield should be the one who actually calls the setText method. So in most cases, that would be the activity. It seems like in this case, your Test class should only provide a method which will return the text you want to display as a string.
So something like
public class MyActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(...);
Test t = new Test(...);
String testText = t.getTestString();
TextView tv = (TextView)findViewById(R.id.TestTextView);
tv.setText(testText)
}
}
public class Test
{
public String getTestString()
{
return "Test"; // Probably would be more dynamic in your case.
}
}
This will abstract the data knowledge out to the Test class. All your activity needs to know is that someone else is providing a data string, and it can set the text itself.

Using Child Class In Android

Sorry, I'm a newbie to Java and Android...
I've made an app that has a big main activity, I'm wanting to split it up into some child classes to make things easier to read, edit etc.
From my main class I (think) I am instantiating, and calling the child class, from within OnResume :
SetupButtons SetupButtonsObject = new SetupButtons ();
SetupButtonsObject.buildthem();
And in the child class I do:
class SetupButtons extends main {
void buildthem(){
//a load of things to setup buttons
}
}
The code I am using in buildthem() works fine when used in the main class, but is giving a nullpointer exception when used in the child class.
do I need to pass the main context to the child or something?
Many Thanks
Tom
Anything you use in the childclass that is not set there, but set in the main class, you must in some way get from the main class. So yeah, you need some context.
But before you do that: you might want to divide your app in classes that are logical parts of your sollution, as you can read in any OOP description. So not just chop it up in parts because it makes it smaller, chop it up in logical units that are actual good objects.
A quick type, hope I did not make any mistakes here, but see comments in child class.
class Parent{
public static int foo = 1;
public static int bar = 0;
public function somefunction(){
bar = 1;
myChild = new Child();
}
}
class Child extends Parent{
//you can find foo = 1
//but not bar = 0;
}
The Activity class isn't supposed to be instantiated by developer directly, leave this work to the android. If you wish to split it up why do you extend your main activity? You rather need to divide your app in logical parts as Nanne said.
In same class you can call that method directly. Like buildthem();

Where should I put global methods and variables in an Android app?

When I'm writing a method or using a member variable, I often find I need to share them across an app. But where should they go?
I can subclass Activity, but that falls over as soon as I use a MapView and am forced to use MapActivity, so not all my activities inherit from my subclass. Is there I way around this?
Where inheritance isn't applicable, I am tending to put generic methods and member variables into a subclass of the Application object, but I'm finding it's creating a mess of code as every class needs to either grab access to the application object through via context, or I have to pass it down.
I suspect I would be better off creating MyApplication.getInstance() and keeping everything in a singleton, instead of passing the application object down through the app classes. but before I wanted to see what you guys had to say.
If you want to access the "Global Singleton" outside of an activity and you don't want to pass the Context through all the involved objects to obtain the singleton, you can just define, as you described, a static attribute in your application class, which holds the reference to itself. Just initialize the attribute in the onCreate() method.
For example:
public class ApplicationController extends Application {
private static ApplicationController _appCtrl;
public static ApplicationController getAppCtrl()
{
return _appCtrl;
}
}
One example with resources: Because subclasses of Application also can obtain the Resources, you could access them simply when you define a static method, which returns them, like:
public static Resources getAppResources()
{
return _appCtrl.getResources();
}
For global methods, use a static Util class with static methods. If you can't use static methods, then the methods shouldn't be global in the first place, and put them in the class that makes sense.
First read this:
How to declare global variables in Android?
Now why you shouldn't use a static singleton. Using a singleton is a the same thing as a global variable. Global variables reduce your maintainability because everywhere you use the global variable you break modularity or introduce global details and assumptions about your overall design. Your program can't have two of these variables because it only looks in one place for it. This means your program can't adapt easily when you have two instances instead of one.
For example, say I have a method called playTurn() and I implement it like so:
public void playTurn() {
globalPlayer.incrementClock();
globalPlayer.doSomething();
globalPlayer.doSomethingElse();
}
Now let's say I want to add a second player to the mix. Uh oh my playTurn() method assumes one player only when it used globalPlayer. If I want to add a second player to the program I have to change that method. Do this a lot and your program is very rigid and inflexible to change. Instead what if I did this:
public void playTurn(Player player) {
player.incrementClock();
player.doSomething();
player.doSomethingElse();
}
Now can do this:
playTurn( player1 );
playTurn( player2 );
I can reuse playTurn() for both player1 and player2 and I didn't have to change it. I just had to change the client of that method.
Most of the time you're being lazy and you want to get a reference to some object, and global variables are fast ways to get references to well known objects. Instead it's better to have one class that resolves the dependencies across your application at start up or the time when it makes sense. Then only that one place understands how your code is put together. For example,
public class Game {
Player player1;
Player player2;
Board board;
public void startGame() {
BlueTooth blueTooth = BlueTooth.getChannel();
player1 = new LocalPlayer();
player2 = new NetworkedPlayer( blueTooth );
board = new Board();
player1.setOpponent( player2 );
player1.setBoard( board );
player2.setOpponent( player1 );
player2.setBoard( board );
}
}
Now everyone has their dependencies, and they don't need to use static variables to find references to things. Also player1 doesn't have to know about details like that player2 is over the network, or that it's apart of a Game. What's important to note is that these objects we're connecting have a long life, possibly the entire program, but if they need to create other things at runtime that's ok for them to do.
Say for example, we need to create multiple players at runtime based on who joins the game. Well we might create a PlayerManager that we can instantiate at startup then create Player objects on the fly. PlayerManager is just a plain old object that we create in Game when we start a new game.
I hope you can start seeing this is a much better way to develop software. You might not understand it right off, but if you think about it will make more sense. It's very subtle change, but very powerful.

Categories

Resources