2010-11-10 39 views
10

Tôi nên sử dụng điều nào sau đây để đảm bảo rằng tất cả các con trỏ đều bị đóng?Thành ngữ để đóng một con trỏ

Cursor c = getCursor(); 

    if(c!=null && c.getCount()>0){ 
     try{ 
      // read values from cursor 
     }catch(..){} 
     finally{ 
      c.close(); 
     } 
    }//end if 

    OR 

    Cursor c = getCursor(); 
    try{ 
     if(c!=null && c.getCount()>0){ 
      // read values from cursor 
     }//end if 
    }catch(..){ 

    }finally{ 
     c.close(); 
    } 

EDIT:
Một vài câu hỏi:
1. Đỗ chúng ta cần phải gọi close() trên một con trỏ đó có tổng số là 0?
2. Bởi vì trong trường hợp đó cho thành ngữ đầu tiên, close() sẽ không bao giờ được gọi. Giả định rằng đối với con trỏ không có phần tử, con trỏ sẽ không bao giờ được mở. Đây có phải là giả định hợp lệ không?

Vui lòng thông báo.

Trả lời

13

Không, nhưng điểm thứ hai là gần nhất.

  • Lựa chọn 1 không đúng cách đóng Cursor khi getCount() == 0
  • Lựa chọn 2 rời khỏi khối finally tiếp xúc với một con trỏ ngoại lệ vô

Tôi sẽ sử dụng:

Cursor c = getCursor(); 
try { 
    if(c!=null && c.getCount()>0){ 
     // do stuff with the cursor 
    } 
} 
catch(..) { 
    //Handle ex 
} 
finally { 
    if(c != null) { 
     c.close(); 
    } 
} 

... hoặc nếu bạn dự kiến ​​con trỏ sẽ không có giá trị thường xuyên, bạn có thể biến nó trên đầu một chút:

Cursor c = getCursor(); 
if(c != null) { 
    try { 
     if(c.getCount()>0) { 
      // do stuff with the cursor 
     } 
    } 
    catch(..) { 
     //Handle ex 
    } 
    finally { 
     c.close(); 
    } 
} 
+0

cảm ơn câu trả lời của bạn! –

+0

tôi không nghĩ rằng sử dụng getCount là một phương pháp tốt. nếu bạn sử dụng moveToFirst, bạn có thể nhận được hiệu suất tốt hơn – wangzhengyi

+0

@wangzhengyi - Đó là một điểm di chuyển hợp lệ và có câu trả lời cho câu hỏi "có điều gì trong tập kết quả" ... nhưng OP đã sử dụng getCount() trong ví dụ của họ để tôi tiếp tục ở đây. –

0

Phụ thuộc vào những gì bạn đang bắt, nhưng tôi muốn nói điều thứ hai, chỉ trong trường hợp c.getCount() ném ngoại lệ.

Ngoài ra, một số thụt đầu dòng sẽ không đi không ổn :)

0

tôi muốn nói là người đầu tiên, chủ yếu là do điều thứ hai sẽ cố gắng gọi c.close() ngay cả khi cnull. Ngoài ra, theo các tài liệu, getCount() không ném bất kỳ ngoại lệ nào, do đó, không cần phải bao gồm nó trong khối try.

+0

Chúng ta có cần gọi close() trên con trỏ có tổng số là 0 không? Bởi vì trong trường hợp đó cho thành ngữ đầu tiên, close() sẽ không bao giờ được gọi. Giả định rằng đối với con trỏ không có phần tử, con trỏ sẽ không bao giờ được mở. Đây có phải là giả định hợp lệ không? –

+0

Không. Một con trỏ 'Cursor' cần được đóng lại cho dù có bao nhiêu mục. – Felix

+0

Bạn chỉ có thể bỏ qua điều kiện 'c.getCount()> 0'. Bằng cách này, con trỏ của bạn sẽ luôn luôn bị đóng và khối 'try' của bạn sẽ không làm gì cả. – Felix

1

Thực hành tốt nhất là dưới đây:

Cursor c = null;  
try {   
    c = query(....);  
    while (c.moveToNext()) { // If empty or next to last record it returns false.  
     // do stuff..  
    } 
} finally { 
    if (c != null && !c.isClosed()) { // If cursor is empty even though should close it.  
    c.close(); 
    c = null; // high chances of quick memory release. 
} 
+0

Tôi tự hỏi nếu trong trường hợp này nó thực sự là thực hành tốt nhất để thiết lập con trỏ để null, vì nó là một biến địa phương, GC nên đủ thông minh để xử lý nó phải không? – Shyri

3

này thậm chí còn tốt hơn:

  • không sử dụng c.getCount() - đếm có thể yêu cầu thêm công việc cho các cơ sở dữ liệu và không phải là cần
  • khởi chạy con trỏ trước khối truy vấn, do đó không thể tạo truy vấn không được theo sau bởi khối cuối cùng

Mã:

Cursor c = query(....); 
if (c != null) { 
    try {   
     while (c.moveToNext()) { // If empty or after last record it returns false.  
      // process row... 
     } 
    } 
    finally { 
     c.close(); 
    } 
} 

Lưu ý rằng c có thể là null trong trường hợp lỗi hoặc con trỏ rỗng. Xem https://stackoverflow.com/a/16108435/952135. Tuy nhiên, tôi sẽ báo cáo giá trị trả về null trong trường hợp con trỏ trống làm lỗi.

+0

NPE là một vấn đề, 'truy vấn' có thể trả về' null'. – Pin

+0

Tôi có nghĩa là không có kiểm tra 'c! = Null' là cần thiết cuối cùng. Nếu truy vấn trả về null, nó sẽ thất bại với NPE, giống như đoạn mã của Hemant. Và tôi nghĩ phương thức 'query()' sẽ không bao giờ trả về null. Nó sẽ tạo ra các truy vấn, hoặc ném một ngoại lệ, trong trường hợp này bạn không cần phải chạy khối cuối cùng. Đây là mô hình dọn dẹp bình thường: tạo tài nguyên ... thử ... làm việc ... cuối cùng ... dọn dẹp ... kết thúc. Nếu việc tạo không thành công, nó được báo cáo. Nếu công việc thất bại hoặc thành công, cuối cùng thì dọn dẹp. Nếu bạn hiểu, vui lòng xóa bỏ phiếu phủ định. Nếu không, xin vui lòng viết. – Oliv

+1

Nó có thể trả về null và được chỉ định trong tài liệu (xem ContentResolver.query). Ngoài ra, hãy kiểm tra điều này: http://stackoverflow.com/questions/13080540/what-causes-androids-contentresolver-query-to-return-null – Pin

-1

Tôi nghĩ rằng câu trả lời của tôi là tốt nhất:

Cursor cursor = null; 

    try { 
     cursor = rsd.rawQuery(querySql, null); 
     if (cursor.moveToFirst()) { 
      do { 
       // select your need data from database 
      } while (cursor.moveToNext()); 
     } 
    } finally { 
     if (cursor != null && !cursor.isClosed()) { 
      cursor.close(); 
      cursor = null; 
     } 
    } 
+0

nếu câu trả lời này không tốt, hãy cho tôi biết lý do bạn cho rằng mô hình này tồi tệ hơn – wangzhengyi

-1

Tôi nghĩ @ skylarsutton là một câu trả lời đúng cho câu hỏi này.Tuy nhiên, tôi muốn để lại mã cho câu hỏi (bất kỳ mã nào trong câu trả lời dường như có một số sai sót). Vui lòng xem xét sử dụng mã của tôi.

Cursor c = query(....); 
if (c != null) { 
    try {   
     //You have to use moveToFirst(). There is no quarantee that a cursor is located at the beginning. 
     for(c.moveToFirst();!c.isAfterLast();c.moveToNext()) { 
      // process row... 
     } 
    } 
    finally { 
     c.close(); 
    } 
} 
Các vấn đề liên quan