getApplicationContext() throws an exception when used - android

I've specified a class, based on another one in an existing Android project. The addRow() method is supposed to dynamically add rows to a table.
When creating a new TextView to add to my row and also when creating that row, I'm supposed to specify the "context". The current way, trying "getApplicationContext()" throws a NullPointerException.
So where am I supposed to get that context from?
public class DistanceTableView extends ContactListActivity
{
public void addRow(LocationMessage locationMsg){
View messageView = theInflater.inflate(R.layout.homepage, null);
TableLayout table = (TableLayout)messageView.findViewById(R.id.distanceTable);
TextView senderNameTextView = new TextView(getApplicationContext());
senderNameTextView.setText(locationMsg.getSenderName());
TableRow tr = new TableRow(getApplicationContext());
tr.addView(distanceTextView);
table.addView(tr);
rows.addFirst(messageView);
}
}
The class that my view is extending:
public class ContactListActivity extends MapActivity implements
ConnectionListener {}

I guess you have to pass the context to the constructor of your class.

Try this instead:
TableRow tr = new TableRow(this);

Related

android: after async process get data back from onPostExecute to view OR pass view to onPostExecute

i am trying to add extra input fields on the fly to my view.
i first read json string from url with an async funct and map this dynamically to an object with a hasmap with GSON.
next i want to iterate the hashmap to create and add the input fields:
public class NewProductActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_product);
TextView view = (TextView) this.findViewById(android.R.id.content);// is this the correct way to get view?
new loadTemplateAttributes(view).execute();// android studio complains about passing view here
.. snip...
class loadTemplateAttributes extends AsyncTask<String, String, HashMap> {
HashMap mymap;
.. snip...
protected void onPostExecute(HashMap mymap) {
pDialog.dismiss();
Iterator it = mymap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
String name = (String) pair.getKey();
TemplateAttribureProperties t = (TemplateAttribureProperties) pair.getValue();
String type = t.getType();
System.out.println("Name=" + name + " type=" + type);
LinearLayout ll = (LinearLayout) findViewById(R.id.linearLayout2);
// add text view
TextView tv = new TextView(this); // 'this' is unknow here
tv.setText(name);
ll.addView(tv);
EditText et = new EditText(view); // 'view' is what i want to pass but dont know how
et.setText();
ll.addView(et);
it.remove();
}
problem is that 'this' is unknown inside onPostExecute function.
i read something about passing the view to the async function but to me it is unclear how to get the view in the firstplace and how to pass it after...
also a lot of options dont seem to work because they are deprecated or are unsafe because the might introduce memory leaks according to the comments.
really lost here.
I don't know what you are doing but You can use Context context; and TextView view; before onCreate() making it global and then you can callTextView tv = new TextView(context); in your method.
public class NewProductActivity extends Activity {
Context context=this;
private TextView view;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_product);
view = (TextView) findViewById(android.R.id.content);
}
new loadTemplateAttributes(view).execute();// android studio complains about passing view here
you would have to add constructor to your asynctask, like that:
class loadTemplateAttributes extends AsyncTask<String, String, HashMap> {
View view;
public loadTemplateAttributes(View v) {
view = v;
}
TextView tv = new TextView(this); // 'this' is unknow here
from internal class in java, you refer to parent class using NewProductActivity.this syntax in your case.
EditText et = new EditText(view); // 'view' is what i want to pass but dont know how
et.setText();
you could use aproach with constructor as I described above, or refer directly to activity view: NewProductActivity.this.view. But you would have to make view a class field in your activity.
Advanced: making your activity an internal class instead of static, and also passing views to it, might cause reference leaks and also crashes in case you use view (inside AsyncTask) that was invalidated due to screen rotation. This is especially possible if your AsyncTask is doing network operations. To prevent it always make AsyncTasks static, also if you pass views or activities to them, then wrap those references in WeakReference<>

How to clear and add new texts to a dynamically created TextView?

I have added a TextView dynamically in a loop. On a button click, I want to clear the existing text in the text view and set some other text to it. How can I do this?
This is my current code:
ArrayList<String> Cheif_ComplaintNew = new ArrayList<String>();
int cc_Arraylist_length = Cheif_ComplaintNew.size();
android.widget.TextView cc_new = new android.widget.TextView(getApplicationContext());
for(int i=0; i<cc_Arraylist_length; i++)
{
cc_new.setId(i);
cc_new.setText(Cheif_ComplaintNew.get(i));
cc_new.setTextColor(getResources().getColor(R.color.black));
cc_new.setTypeface(null,android.graphics.Typeface.ITALIC);
cc_new.setTextSize(14);
cc_linearNew.addView(cc_new);
System.out.println("id"+i);
}
On a button click, the list is cleared and new data is stored in it. I want to display the new data in the same text view by clearing the old one.
You can either add the text to the textbox when you are creating it or assign it a class variable when you create it and later on you can add text to it.
TextView dynamicTextView;
...
private void CreateNewTextView()
{
dynamicTextView = Your New Text View;
}
...
private void ChangeTheText()
{
dynamicTextView.SetText("new value");
}
if you have more than one TextView you can create a class level generic list of TextViews and add them to the list and call them later.
you can also create a map of all TextView so you can call them with their key as well.
I think you can set a tag to cc_new before add it to cc_linearNew, like this: cc_new.setTag(i). when button got click, you can find those TextView by cc_linearNew.findViewByTag(i) in loop, and set new data to them.
Depends on how many TextViews you need to add to the layout dynamically.
As per the code mentioned, no TextViews are added to the layout as: Cheif_ComplaintNew.size() would return "0" so your loop will not be executed.
If you have to add only one TextView, then I agree with Daniel's answer of having a class level TextView variable.
If its multiple TextViews and you know which ID to use then in your Activity you can always get that TextView by calling findViewById("ID_OF_THE_TEXTVIEW_NEEDED")
You can do this in many ways, some of them :
Store your just created ids in array. Then just get your views calling parentView.findViewById(arreyOfIds(0));
Bad for performance do not do this :) - remove all of just added views from your parentView and create them one more time.
To handle back click in Activity use :
#Override
public void onBackPressed()
{
clearTextView();
}
All of this will simple look like this :
private List<Integer> ids = new ArrayList<Integer>();
#Override
public void onBackPressed()
{
clearTextView();
}
private void clearTextView()
{
for(Integer id : ids)
{
TextView view = (TextView)findViewById(id);
view.setText("")
}
}
private void createTextViews()
{
ArrayList<String>Cheif_ComplaintNew = new ArrayList<String> ();
int cc_Arraylist_length=Cheif_ComplaintNew.size();
android.widget.TextView cc_new = new android.widget.TextView(getApplicationContext() );
for(int i=0; i<cc_Arraylist_length; i++)
{
ids.add(i)
cc_new.setId(i);
cc_new.setText(Cheif_ComplaintNew.get(i));
cc_new.setTextColor(getResources().getColor(R.color.black));
cc_new.setTypeface(null,android.graphics.Typeface.ITALIC);
cc_new.setTextSize(14);
cc_linearNew.addView(cc_new);
System.out.println("id"+i);
}
}

Find List item that populated clicked Table-layout row:

I have an activity that contains a TableLayout. I'm populating this table programmaticly by data i have in a list:
what i need to do is to make every row clickable and when it's click I need to find the corresponding item in the list so i can get extra data out of it, this is my onCreate code:
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.reports_list_activity_layout);
application = (SGRaportManagerAppObj)getApplication();
reportsRepository = application.reportsRepository.getReportsRepository();
TableLayout table = (TableLayout) findViewById(R.id.tableReportsList);
table.setStretchAllColumns(true);
table.setShrinkAllColumns(true);
for (Report tempReport : reportsRepository)
{
TableRow row = new TableRow(this);
row.setClickable(true);
TextView tvName = new TextView(this);
tvName.setText(tempReport.getName());
tvName.setGravity(Gravity.CENTER_HORIZONTAL);
tvName.setTextColor(getResources().getColor(R.color.my_black));
row.addView(tvName);
TextView tvPath = new TextView(this);
tvPath.setText(tempReport.getPath());
tvPath.setGravity(Gravity.CENTER_HORIZONTAL);
tvPath.setTextColor(getResources().getColor(R.color.my_black));
row.addView(tvPath);
row.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
Map<String, String> map = new HashMap<String, String>();
map.put(Report.JSON_KEY_ID, );
}
});
table.addView(row);
}
}
so what I need here is when the row is clicked i need to find it in the list and get the ID of the report that was clicked in the table and put into the Map object to pass foreword.
does anyone know how is this can be done?
thanks.
Use a hashtable that maps the content you show in the table row (say Report ID) againsg the Report Object
So something like
Hashtable map = new Hashtable();
...
map.put(report.getId(), report);
onClick on table row, manage to get the report id and in turn look it up this hashtable you are maintaining at a class level or somewhere accessible ..
Edit(code block)
class MyTableRow extends TableRow{
Object report = null;
public MyTableRow(Context context) {
super(context);
}
public Object getReport() {
return report;
}
public void setReport(Object report) {
this.report = report;
}
}
in the onCreate() of your activity, jus use MyTableRow class instead of TableRow like
tableRow = new MyTableRow(this) and use tableRow.setMethod(reportObject) to set the Report. should work..

Add new LinearLayout on each iteration of Activity

In one of my activities, I create a Linear Layout and some other Widgets when a bundle is received from an Intent. Currently, that Layout is overwrited each time I come back to that Activity. How can I create a new Layout each time without rewriting the code?
CODE:
public class FrontPageActivity extends Activity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.frontpage);
Bundle bundle = this.getIntent().getExtras();
try{
String size = bundle.getString("size");
int toppcount = bundle.getStringArrayList("toppings").toArray().length;
LinearLayout container = (LinearLayout)findViewById(R.id.container);
TextView t = new TextView(this);
TextView tprice = new TextView(this);
tprice.setGravity(Gravity.RIGHT);
LinearLayout inner = new LinearLayout(this);
LinearLayout.LayoutParams innerparams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
inner.setLayoutParams(innerparams);
inner.setBackgroundDrawable(getResources().getDrawable(R.drawable.background));
inner.setPadding(10,10,10,10);
if(toppcount == 0){
t.setText(size+" Cheese Pizza");
}
else{
t.setText(size+" "+toppcount+" Topping Pizza");
}
tprice.setText(getPrice(size, toppcount)+"");
tprice.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT));
container.addView(inner);
inner.addView(t);
inner.addView(tprice);
}
catch(NullPointerException e){
}
final Intent sender = new Intent(this.getApplicationContext(), OrderPizzaActivity.class);
Button badd = (Button)findViewById(R.id.buttonaddpizza);
badd.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
startActivityForResult(sender, 0);
}
});
}
It sounds like you would need to create a data structure to hold the LinearLayouts, or provide a ViewGroup container for them to be added to each time.
Currently you are creating, modifying, and then overwriting the same LinearLayout in the try{} catch(){} block. Which I would guess to be the reason why it keeps overwriting.
As I understood you add new "options" to the "final order". Every time additional topping added you create a layout and fill it with specific data. And you want it to be aka OrderList. If what this app is about, you can have an application level variable myOrder:List. Add there toppings (topping = new Order()) and read list in FrontPageActivity.
Recommend you to have a separate layout for an order. Looping through orders fill layout with data and inflate in a container of Activity.
Idea in pseudo:
MyApplication extends Application {
private static List<Order> mOrderList = null;
public MyApplication(){
mOrderList = new ArrayList<Order>();
}
public static List<Order> getOrderList(){
return mOrderList();
}
public static void addOrder(Order order) {
mOrderList.add(order);
}
}
options activity:
MyApplication.add(order);
MyApplication.add(order);
FrontPageActivity
foreach(Order order : MyApplication.getOrderList()) {
// fill layout with order data
// inflate orderLayout into container
}

Android TableLayout not Displaying

I've got a class whose content is set to a layout which has a few buttons and a TableLayout.
The real work that makes the TableLayout is in a separate static helper class, which has a method that returns the desired table.
However, the table is not displaying. What humiliatingly simple fact am I missing?
Here is the class whose content is set to the layout:
public class TesterActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TableLayout table = (TableLayout) findViewById(R.id.table);
table = TableHelper.getTable_BINARY_NUMBERS(getApplicationContext(), 5, 25);
}
}
And here is the helper class that creates the Table's meat:
public class TableHelper {
public static TableLayout getTable_BINARY_NUMBERS(Context context, int numRows, int numCols) {
TableLayout table = new TableLayout(context);
table.setStretchAllColumns(true);
table.setShrinkAllColumns(true);
TableRow[] rows = new TableRow[numRows];
for (int row=0; row<numRows; row++) {
rows[row] = new TableRow(context);
for (int col=0; col<numCols-1; col++) {
TextView num = new TextView(context);
num.setText("0");
rows[row].addView(num);
}
TextView rowText = new TextView(context);
rowText.setText("Row " + (row + 1));
rowText.setTextAppearance(context, android.R.style.TextAppearance_Small);
rows[row].addView(rowText);
rows[row].setPadding(0, 50, 0, 0);
table.addView(rows[row]);
}
return table;
}
}
Instead of returning a new table layout, pass the one you get right away to your getTable_BINARY_NUMBERS() and modify it in your method instead of returning a completely new one.
The TableLayout your helper class is returning is not the same as the TableLayout that you are seeing.
when you do setContentView(R.layout.main); an instance of TableLayout is created which you assign to the variable table. The TableLayout coming from your helper class is a different instance.

Categories

Resources