I know it's not the best practice, but I have a few layouts (only one is visible at a time)
with the same view_id in all of them.
Is there any way method to get all views with this id?
I can iterate all layouts and layout.findViewById() but wanted to ask if there is something similar to a CSS findViewsById() views instead of view
Activity::findViewById() returns just the first one.
No, there is no method like that. If some "dirty hack" exists it will be unstable.
"Best practice" here will be iterate layouts and store references on these views in array.
You can make your own. In that case you have to use setContentView(View) instead. So your findViewsById() would be,
public View[] findViewsById(int id) {
View[] views = new View[contentViews.length];
for(int i=0; i<contentViews.length; i++) {
views[i] = contentViews[i].findViewById(id);
}
return views;
}
Your activity should look like the following,
private View[] contentViews;
#Override
public void onCreate(Bundle si) {
super.onCreate(si);
populateContentViews();
setContentView(contentViews[x]);
...
}
Of course you can.
Just do it in recursion:
For each view check its ID, and do it for its children.
That's it.
After all, that's almost what findViewById does. It searches in the view hierarchy like a recursion, till it finds it.
Related
It's quite hard to put My doubt in words but ill try, Hi there I am creating simple book app where user can learn different languages like java,c,c++, and I got and question mark here. my question is how can I control/Inflate more than one RecycleView activity from an adapter class or should I make different RecycleViewand and adapter system for every single language.
i.e I just want an app having multiple buttons with different languages where user can click on the button and learn programming concept listed there he can come back and click another button in order to learn another language as well
"I hope you got my point"
You must use different data
Also you can use different layout for any item
in your model.class (model of data for recyclerView you can define a variable for Type of data
ex :
public String getType() {
return Type;
}
public void setType(String Type) {
this.Type= Type;
}
i use from this setter and getter
so in your addapter class insert below method
#Override
public int getItemViewType(int position) {
return ;
}
with this method you can pass any value you want and get it as int i in myViewHohder onCreateViewHolder method
public myViewHohder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
return ;
}
and you can with a (if) Condition to decide for layout of item
I am trying to add element in my arraylist from different method. But i want to know that its a right way to go ahead, if not plaase suggest best way of it
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
List<String>links=new ArrayList<>();
addLinkFromServerOne(links);
return view;
}
private void addLinkFromServerOne(final List<String> links)
{
...
String link=".....";
links.add(link);
addLinkFromServerTwo(links);
}
private void addLinkFromServerTwo(final List<String> links)
{
...
String link=".....";
links.add(links);
checkStatus(links);
}
private void checkStatus(links)
{
Toast.makeText(getActivity(), String.valueOf(links.size()), Toast.LENGTH_SHORT).show();
}
Actually, it is quite good practice to wrap interactions with collections inside of class storing it. Also, that is not good practice to expose collections to other classes. That might be dangerous and confusing further because you can not only add but also remove elements from list. And that means inconsistent data.
Long story short: you are doing great!
Unless you are doing anything more than that (for example, if that methods are on a different thread (Async)), that is correct.
I am fairly new to Android Development and I have been stuck at this for some time. I've tried searching but nothing that really answers my question.
Scenario:
I have a Recycler view w/ an Adapter & viewholder (the usual)
My Adapter takes 2 lists.
exampleListA & exampleListB.
exampleListA is a Fruit object & exampleListB is a Pricing Object
These lists are coming back from a network call, where Fruit objects are coming in first.
My problem:I need to sort the list by the Pricing object, from least to highest. I tried Collections.sort(exampleListB ...) , the list gets sorted (I did a log) but it seems the recyclerview will always make exampleListA take importance over the other.
What is the best way, maybe even simplest (though I am not afraid to do some work) to sort exampleListA in order of a property in exampleListB ??
Anything would help, thanks!
public class GroceriesAdapter extends RecyclerView.Adapter<GroceriesAdapter.Viewholder>{
///.... generic stuff
public GrocereisAdapter(ArrayList<Fruit> fruitList, ArrayList<Pricing> pricingList){
this.fruitList = fruitList;
this.pricingList = pricingList;
void onBindViewHolder(Viewholder holder, int position){
Fruit fruit = fruitList.get(position);
Pricing price = pricingList.get(position);
holder.fruitTitle.setText(fruit.getName);
holder.pricingPrice.setText(price.getPrice);
public class MainActivity ....
//General OnCreate & variables...
ArrayList<Fruit> fruitList = new ArrayList();
ArrayList<Pricing> priceList = new ArrayList();
public void loadData(){
//Does Rest Call..
fruitList.addAll(restResponse.getFruitObjects);
priceList.addAll(restResponse.getPriceObjects);
now originally I thought this would work.. but it isn't. But just so you know what I Tried;
//After rest call, before adding them to lists.
Collections.sort(priceList, new Comparator<Pricing>) {
//general code that comes up when calling this..
return Double.compare(price.getPrice, p1.getPrice);
Thats pretty much it, nothing too too fancy. just taking properties from one list and the other and creating my views. *(Note edited for the project I'm working on)
most of my apps are apps with just one screen (due to the functionality) sometimes being extended by "floating" popups that are basically RelativeLayouts (containing other UI elements) that are being added to the Main layout, keeping the UI Elements of the Main layout active and "touchable" in the background.
For a better understanding, please just look at the sketch (purely symbolic):
If you include all the stuff from the popups as well, I have about 90 UI elements, a dozen of custom View classes like buttons, sliders, ... at a time, all of them needing to have certain listeners running on them, all of them having to be resized on start up [...]
I, in fact, write quite efficient (in terms of amount of bytes used) code, and if there is a 3-line method to return a value that replaces 4 lines of additional code, I write this method just to satisfy myself. However, I quite don't understand how to outsource code from my MainActivity to other classes. Of course, if there is a calculation to be made, this is something that I put into another class rather than just creating a method in my MainActivity class. Anyway, my MainActivity is now at 1600 lines of code which is an awful amount of text to overview for debugging, adding or changing code. The variable declarations of my UI elements alone take 100 lines of code (maybe 70 lines if compressed)
That was the longest explanation I ever made for a post but now we get to my question:
How can/do you outsource code like listeners, UI stuff like findViewById() or similar things to other classes? Are there common practices to do so in an efficient way? I don't want to go for clumsy workarounds that skyrocket the CPU, so "smooth" stuff is stuff I am looking for.
It might be KIND OF off-topic but I hope it's ok to be asked here.
I'm not sure that there is particular answer on your question because I suppose it's all about experience which you can get reading source code of other projects for instance. But I have few advices which could help you:
1. Use libraries which eliminate boilerplate code like findViewById and listeners. One of them is Butterknife
7 lines of code:
View text = findViewById(R.id.text_id);
text.setOnClickListener(
new View.OnClickListener() {
#Override public void onClick(View v) {
//
}
}
);
2 lines code:
#OnClick(R.id.text_id) public void handleClickOnText() {
//
}
2. Use static helper classes:
4 lines of code:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(R.string.new_message);
builder.setTitle(R.string.create_calendar_title);
builder.show();
1 line of code:
DialogsHelper.newMessage(this);
3. Read about MVP. It's about modular app architecture. Roughly speaking it helps to divide raw View from logic.
Basic sample:
public static class SomePresenter {
private SomeView view;
public SomePresenter(SomeView view) {
this.view = view;
view.showProgressLoading();
loadData();
}
private void loadData(){
//loading data from some server
}
private void loadingDataHandler(SomeModel model){
view.showData(model);
}
}
public static class SomeView extends View{
#Inject(R.id.text_progress_title) TextView text;
public SomeView(Context context) {
super(context);
ButterKnife.inject(this);
}
public void showData(SomeModel model){
text.setText(model.dataA + ":" + model.dataB);
}
public void showProgressLoading(){
text.setText(R.string.progress);
}
}
public static class SomeModel{
public final int dataA;
public final int dataB;
}
And your onCreate method of activity could look like this:
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
new SomePresenter(someView);
}
// use case 10b alternate version
// caches a read comment temporarily
public void testCacheReadComment2() throws Throwable{
runTestOnUiThread(new Runnable()
{
#Override
public void run(){
CommentBuilder commentBuilder = new commentBuilder();
Comment comment = commentBuilder.createTopTestComment();
//browse button on main screen
((Button)activity.findViewById(ca.ualberta.cs.team5geotopics.browseButton)).performClick();
//the ListView for the custom adapter
ListView listView = (ListView) activity.findViewById(ca.ualberta.cs.team5geotopics.commentList);
//the custom adapter on the physical screen
ArrayAdapter<Comment> adapter = (ArrayAdapter<Comment>) listView.getAdapter();
adapter.add(comment);
adapter.notifyDataSetChanged();
View view = adapter.getView(adapter.getPosition(comment), null, null);
ViewAsserts.assertOnScreen(listView, view);
//this is the button to view the Top Level comment in the list
ViewAsserts.assertOnScreen(view, (Button) view.viewTopLevelComment);
((Button)view.viewTopLevelComment).performClick();
// is there a way I can get references to the objects
// already instantiated in the test thread?
CacheController cc = activity.getCacheController();
assertTrue(cc.getHistory().contains(comment));
}
});
}
We are using a test driven development style in order to code our project for school. In this test I am trying to prove that after a user views a comment from the list in the adapter, that this comment is cached in a history cache. I'm a little confused about some things and I would like some help, because it would be great if I knew there were no obvious flaws in my test case. these are my questions:
View view = adapter.getView(adapter.getPosition(comment), null, null);
Will this line return the view that is associated with the comment stored in the array adapter? My ArrayAdapter is going to follow a holder patter and I'm not sure if this is the proper way to get access to the buttons I need to mimic the user viewing the comment.
CacheController cc = activity.getCacheController();
I have a CacheController object that is instantiated upon the onCreate() method in our main activity. Now I want to reference this CacheController to see if the history is updated properly. I was just making a new CacheController and mimicking the actions of the CacheController in the test method, but I want to test what happens to my data on the UIthread. So, how do I reference objects in the UI thread?
View view = adapter.getView(adapter.getPosition(comment), null, null);
Will this line return the view that is associated with the comment
stored in the array adapter?
I think it should work, but I don't understand why would you want to access the View.
My ArrayAdapter is going to follow a holder patter and I'm not sure if
this is the proper way to get access to the buttons I need to mimic
the user viewing the comment.
The ArrayAdapter is usually used for a ListView. You should just let ListView handle the click capturing and tell you which element was clicked.
So, how do I reference objects in the UI thread?
You have 2 solutions for this that come to my mind right now:
1) Pass the CacheController instance, for example:
public class YourClass {
private final CacheController cacheController;
public YourClass(final CacheController cacheController) {
this.cacheController = cacheController;
}
public void testCacheReadComment2() throws Throwable {
CacheController cc = this.cacheController;
}
}
2) Singleton: make the CacheController static and put an accessor, for example:
public class CacheController {
private final CacheController instance = new CacheController();
public static CacheController getCacheController() {
return instance;
}
}
In both cases you should be aware about potential multi-threading issues because you're spawning new threads that all share same CacheController instance.